polygon_t* polygon_star(point_t* x0, point_t* points, int num_points) { ASSERT(num_points > 2); ASSERT(all_points_are_coplanar(points, num_points)); // Find the plane of the polygon. vector_t normal; compute_normal(points, num_points, &normal); point_t xp; compute_centroid(points, num_points, &xp); sp_func_t* plane = plane_new(&normal, &xp); // Find the angles of the points within the plane, and sort the points // by this angle. point2_t pts[num_points]; for (int i = 0; i < num_points; ++i) plane_project(plane, &points[i], &pts[i]); point2_t xc; plane_project(plane, x0, &xc); polygon2_t* poly2 = polygon2_star(&xc, pts, num_points); // Read off the vertex ordering from the planar polygon. ASSERT(polygon2_num_vertices(poly2) == num_points); int* ordering = polygon2_ordering(poly2); // Create our polygon with the given ordering. polygon_t* poly = polygon_new_with_ordering(points, ordering, num_points); // Clean up. poly2 = NULL; plane = NULL; return poly; }
polygon_t* polygon_giftwrap(point_t* points, int num_points) { ASSERT(num_points > 2); ASSERT(all_points_are_coplanar(points, num_points)); // Find the plane of the polygon. vector_t normal; compute_normal(points, num_points, &normal); point_t x0; compute_centroid(points, num_points, &x0); sp_func_t* plane = plane_new(&normal, &x0); // Do the gift-wrapping in 2D. point2_t pts[num_points]; for (int i = 0; i < num_points; ++i) plane_project(plane, &points[i], &pts[i]); polygon2_t* poly2 = polygon2_giftwrap(pts, num_points); #if 0 // Re-embed the resulting vertices in 3D. int num_vertices = polygon2_num_vertices(poly2); point_t vertices[num_vertices]; int pos = 0, offset = 0; point2_t* vtx; while (polygon2_next_vertex(poly2, &pos, &vtx)) plane_embed(plane, vtx, &vertices[offset++]); #endif // Read off the vertex ordering from the planar polygon. Note that // not all of the vertices will be used in general. int num_p2_points = polygon2_num_vertices(poly2); int* ordering = polygon2_ordering(poly2); // Create our polygon with the given ordering. polygon_t* poly = NULL; if (num_p2_points < num_points) { point_t p2_points[num_p2_points]; for (int i = 0; i < num_p2_points; ++i) point_copy(&p2_points[i], &points[ordering[i]]); poly = polygon_new(p2_points, num_p2_points); } else poly = polygon_new_with_ordering(points, ordering, num_points); // Clean up. poly2 = NULL; plane = NULL; return poly; }
collision sphere_collide_ctri(sphere s, vec3 v, ctri ct) { if (!sphere_swept_intersects_plane(s, v, plane_new(ct.a, ct.norm))) { return collision_none(); } collision col = sphere_collide_face(s, v, ct); if (col.collided) { return col; } col = collision_merge(col, sphere_collide_edge(s, v, ct.a, ct.b)); col = collision_merge(col, sphere_collide_edge(s, v, ct.b, ct.c)); col = collision_merge(col, sphere_collide_edge(s, v, ct.c, ct.a)); col = collision_merge(col, sphere_collide_point(s, v, ct.a)); col = collision_merge(col, sphere_collide_point(s, v, ct.b)); col = collision_merge(col, sphere_collide_point(s, v, ct.c)); return col; }
collision point_collide_ctri(vec3 p, vec3 v, ctri ct) { if (!point_swept_intersects_plane(p, v, plane_new(ct.a, ct.norm))) { return collision_none(); } collision col = point_collide_face(p, v, ct); if (col.collided) { return col; } col = collision_merge(col, point_collide_edge(p, v, ct.a, ct.b)); col = collision_merge(col, point_collide_edge(p, v, ct.b, ct.c)); col = collision_merge(col, point_collide_edge(p, v, ct.c, ct.a)); col = collision_merge(col, point_collide_point(p, v, ct.a)); col = collision_merge(col, point_collide_point(p, v, ct.b)); col = collision_merge(col, point_collide_point(p, v, ct.c)); return col; }
sp_func_t* rect_prism_new(point_t* x0, real_t L1, real_t L2, real_t L3, real_t alpha, real_t beta, real_t gamma) { ASSERT(L1 > 0.0); ASSERT(L2 > 0.0); ASSERT(L3 > 0.0); // FOR NOW, we disable Euler angles. if ((alpha != 0.0) || (beta != 0.0) || (gamma != 0.0)) polymec_error("rect_prism_new: Euler angles not yet implemented!"); // Set the 6 bounding planes. vector_t n; point_t x; sp_func_t* planes[6]; // "-x" direction n.x = 1.0, n.y = 0.0, n.z = 0.0; x.x = x0->x - 0.5*L1, x.y = x0->y, x.z = x0->z; planes[0] = plane_new(&n, &x); // "+x" direction n.x = -1.0, n.y = 0.0, n.z = 0.0; x.x = x0->x + 0.5*L1, x.y = x0->y, x.z = x0->z; planes[1] = plane_new(&n, &x); // "-y" direction n.x = 0.0, n.y = 1.0, n.z = 0.0; x.x = x0->x, x.y = x0->y - 0.5*L2, x.z = x0->z; planes[2] = plane_new(&n, &x); // "+y" direction n.x = 0.0, n.y = -1.0, n.z = 0.0; x.x = x0->x, x.y = x0->y + 0.5*L2, x.z = x0->z; planes[3] = plane_new(&n, &x); // "-z" direction n.x = 0.0, n.y = 0.0, n.z = 1.0; x.x = x0->x, x.y = x0->y, x.z = x0->z - 0.5*L3; planes[4] = plane_new(&n, &x); // "+y" direction n.x = 0.0, n.y = 0.0, n.z = -1.0; x.x = x0->x, x.y = x0->y, x.z = x0->z + 0.5*L3; planes[5] = plane_new(&n, &x); rect_prism_t* p = polymec_malloc(sizeof(rect_prism_t)); p->prism = intersection_new(planes, 6); // Set up the spatial function. sp_func_vtable vtable = {.eval = prism_eval, .eval_deriv = prism_eval_deriv, .has_deriv = prism_has_deriv, .dtor = prism_free}; char str[1024]; snprintf(str, 1024, "Rectangular prism (x0 = (%g, %g, %g), L1 = %g, L2 = %g, L3 = %g," " alpha = %g, beta = %g, gamma = %g)", x0->x, x0->y, x0->z, L1, L2, L3, alpha, beta, gamma); return sp_func_new(str, p, vtable, SP_FUNC_INHOMOGENEOUS, 1); }
static void polygon_compute_plane(polygon_t* poly) { compute_normal(poly->vertices, poly->num_vertices, &poly->normal); compute_centroid(poly->vertices, poly->num_vertices, &poly->x0); poly->plane = plane_new(&poly->normal, &poly->x0); }
gint load_planes(gchar *filename, struct model_pak *data) { gint h, k, l, num_tokens; gint cflag=FALSE, sflag=FALSE, gflag=FALSE; gdouble m[3]; gchar **buff; GSList *list, *new_planes; struct plane_pak *plane=NULL; struct shift_pak *shift=NULL; FILE *fp; fp = fopen(filename, "rt"); if (!fp) return(1); /* get next line */ new_planes = NULL; for (;;) { buff = get_tokenized_line(fp, &num_tokens); if (!buff) break; /* NB: only update space/cell etc. data if this call did */ /* not originate from an import planes call */ if (data->id == MORPH) { /* cell parameters */ if (g_ascii_strncasecmp(*buff,"cell",4) == 0) { if (num_tokens >= 7) { cflag=TRUE; data->pbc[0] = str_to_float(*(buff+1)); data->pbc[1] = str_to_float(*(buff+2)); data->pbc[2] = str_to_float(*(buff+3)); data->pbc[3] = PI*str_to_float(*(buff+4))/180.0; data->pbc[4] = PI*str_to_float(*(buff+5))/180.0; data->pbc[5] = PI*str_to_float(*(buff+6))/180.0; /* compute direct & reciprocal lattices */ /* NB: enables fn_make_plane() to correctly compute Dhkl */ matrix_lattice_init(data); } else printf("load_planes() error: bad cell line.\n"); } /* space group */ if (g_ascii_strncasecmp(*buff,"space",5) == 0) { if (num_tokens > 1) { sflag=TRUE; data->sginfo.spacename = g_strjoinv(" ", buff+1); data->sginfo.spacenum = 0; } } /* default morphology type */ if (g_ascii_strncasecmp(*buff, "morph", 5) == 0) { if (num_tokens >= 3) { if (g_ascii_strncasecmp(*(buff+1), "unrelaxed", 9) == 0) { if (g_ascii_strncasecmp(*(buff+2), "equil", 5) == 0) data->morph_type = EQUIL_UN; if (g_ascii_strncasecmp(*(buff+2), "growth", 6) == 0) data->morph_type = GROWTH_UN; } if (g_ascii_strncasecmp(*(buff+1), "relaxed", 7) == 0) { if (g_ascii_strncasecmp(*(buff+2), "equil", 5) == 0) data->morph_type = EQUIL_RE; if (g_ascii_strncasecmp(*(buff+2), "growth", 6) == 0) data->morph_type = GROWTH_RE; } } else printf("load_planes() error: bad type line.\n"); } } /* process miller line */ if (g_ascii_strncasecmp(*buff,"miller",6) == 0) { /* init space group (latmat? - if so, remove the make_latmat() in cell parse) */ if (cflag && sflag) { if (!gflag) { if (space_lookup(data)) printf("Error in space group lookup.\n"); gflag = TRUE; } } else { if (data->id == MORPH) { printf("load_planes() error: miller encountered before space or cell.\n"); return(2); } } if (num_tokens >= 4) { h = (gint) str_to_float(*(buff+1)); k = (gint) str_to_float(*(buff+2)); l = (gint) str_to_float(*(buff+3)); #if DEBUG_LOAD_PLANES printf("read plane: %d %d %d\n", h, k, l); #endif VEC3SET(m, h, k, l); /* FIXME - signature change */ /* plane = plane_find(m, data); */ if (!plane) { plane = plane_new(m, data); if (plane) new_planes = g_slist_prepend(new_planes, plane); } } } /* potential data */ if (num_tokens >= 8 && plane) { /* NB: use create_shift(), as it sets some important defaults */ shift = shift_new(0.0); if (shift) { shift->shift = str_to_float(*(buff+0)); shift->region[0] = str_to_float(*(buff+1)); shift->region[1] = str_to_float(*(buff+2)); shift->esurf[0] = str_to_float(*(buff+3)); shift->eatt[0] = str_to_float(*(buff+4)); shift->esurf[1] = str_to_float(*(buff+5)); shift->eatt[1] = str_to_float(*(buff+6)); shift->gnorm = str_to_float(*(buff+7)); #if DEBUG_LOAD_PLANES printf("adding shift: %f\n", shift->shift); #endif /* append to preserve order (eg import on existing plane set) */ plane->shifts = g_slist_append(plane->shifts, shift); } } g_strfreev(buff); } data->planes = g_slist_concat(data->planes, g_slist_reverse(new_planes)); /* compute dhkl's for the plane's list */ for (list=data->planes ; list ; list=g_slist_next(list)) { plane = list->data; /* create default shift if none found */ if (!plane->shifts) { shift = shift_new(0.0); if (shift) plane->shifts = g_slist_append(plane->shifts, shift); } /* get best energy for the plane */ /* FIXME - signature changed */ /* update_plane_energy(plane, data); */ } /* compute symmetry related faces */ /* FIXME - new surface rewrite */ /* surf_symmetry_generate(data); */ fclose(fp); return(0); }