/* See mtv_cup.h */ /* Last edited on 2021-06-22 13:49:21 by jstolfi */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include void mtv_cup_make ( ppv_array_t *A, r3_t *ctr, double cupbotZ, double cuptopZ, double cupR, double cupT, double fuzzR ) { /* !!! Select plain or threaded !!! */ double cupF = 3*cupT; /* Radius of base filet. */ mtv_cup_plain_make(A, ctr, cupbotZ, cuptopZ, cupR, cupT, cupF, fuzzR); } void mtv_cup_plain_make ( ppv_array_t *A, r3_t *ctr, double cupbotZ, double cuptopZ, double cupR, double cupT, double cupF, double fuzzR ) { bool_t debug = FALSE; /* Derived cup parameters: */ double cupmidZ = (cupbotZ + cuptopZ)/2; /* {Z} coordinate of cup center. */ double cupH = fabs(cuptopZ - cupbotZ)/2; /* Half-height of cup. */ if (debug) { fprintf(stderr, "calling {%s}:", __FUNCTION__); fprintf(stderr, " cupmidZ = %.2f halfH = %.2f cupR = %.2f", cupmidZ, cupH, cupR); fprintf(stderr, " cupT = %.2f fillR = %.2f\n", cupT, cupF); } /* Position and orientation of cup: */ r3_motion_state_t state; state.p = (*ctr); state.p.c[2] = cupmidZ; r3x3_ident(&(state.M)); if (cuptopZ < cupbotZ) { /* Upside-down: */ state.M.c[2][2] = -1; } auto double fuzzy_cup(r3_t *p); /* Indicator function for the cup. */ voxm_splat_object(A, fuzzy_cup, &state, hypot(cupH, cupR) + fuzzR, FALSE); return; double fuzzy_cup(r3_t *p) { return voxm_obj_round_cup(p, cupH, cupR, cupT, cupF, fuzzR); } } void mtv_cup_threaded_make ( ppv_array_t *A, r3_t *ctr, double cupbotZ, double cuptopZ, double cupT, double fuzzR, double vsz ) { bool_t debug = FALSE; if (debug) { fprintf(stderr, "enter %s\n", __FUNCTION__); } if (debug) { fprintf(stderr, " Z from %.2f vx to %.2f vx thickness = %.2f vx\n", cupbotZ, cuptopZ, cupT); } demand(cupT > fuzzR, "cup wall thickness is too small"); /* Main cup: */ double inR = 13.8/vsz; /* Inner radius of cup. */ double otR = inR + cupT; /* Outer radius of cup. */ double cupF = 1.2*cupT; /* Radius of base filet. */ if (debug) { fprintf(stderr, " inR = %.2f vx otR = %.2f vx fillet R = %.2f vx\n", inR, otR, cupF); } mtv_cup_plain_make(A, ctr, cupbotZ, cuptopZ, otR, cupT, cupF, fuzzR); /* Threads: */ double thrH = 2.5/vsz; /* Threads rise per turn. */ double thrR = inR; /* Radius of midline of threads helix. */ double thrN = 2.0; /* Number of helix turns. */ double thrZ0 = cupT + 3.5/vsz; /* Distance from cup bottom to start of thread. */ int dirZ = (cuptopZ > cupbotZ ? +1 : -1); /* {Z}-direction of cup. */ double thrbotZ = cupbotZ + dirZ*thrZ0; /* Bottom of thread. */ mtv_cup_thread_make(A, ctr, thrbotZ,dirZ, thrR,thrH,thrN, fuzzR); /* Inner cuplet defining the gasket seat: */ double hgt2 = cupT + 4.5/vsz; /* Total height of cuplet. */ double cupT2 = 1.5/vsz; /* Thickness of cuplet. */ double otR2 = 10.8/vsz; /* Outer radius of cuplet. */ double cupF2 = 1.2*cupT2; /* Fillet radius of cuplet. */ double cupbotZ2 = cupbotZ; /* Bottom of cuplet. */ double cuptopZ2 = cupbotZ + dirZ*hgt2; /* Top of cuplet. */ mtv_cup_plain_make(A, ctr, cupbotZ2, cuptopZ2, otR2,cupT2,cupF2, fuzzR); if (debug) { fprintf(stderr, "exit %s\n", __FUNCTION__); } return; } void mtv_cup_thread_make ( ppv_array_t *A, r3_t *ctr, double thrbotZ, int dirZ, double thrR, double thrH, double thrN, double fuzzR ) { /* Reference state at mid-thread: */ r3_motion_state_t midS; midS.p = (*ctr); midS.p.c[0] += thrR; midS.p.c[2] = thrbotZ + dirZ*thrN*thrH/2; r3_t midU, midV, midW; /* Basis vectors. */ r3_axis(1, &midU); r3_axis(0, &midV); r3_neg(&midV,&midV); r3_axis(2, &midW); r3x3_ident(&(midS.M)); if (dirZ < 0) { /* Upside-down; invert {U} and {W} axes to keep the trhead right-handed: */ r3_neg(&midU, &midU); r3_neg(&midW, &midW); } r3x3_from_rows(&midU, &midV, &midW, &(midS.M)); double otR = thrH/4; /* Radius of thread wire. */ double thrA = 2*M_PI; /* Angle swept in unit time. */ double thrL = thrA*thrR; /* Projected length traversed in unit time. */ voxm_splat_tube_round_helix ( A, -1.00, +1.00, &midS, thrL,thrA,thrH, 0.0, otR, fuzzR, FALSE, NULL, NULL ); }