int get_rot_mat(double R[3][3],double v[3]) /* creates a rotation matrix that transforms v into z' */ { /* with (y' dot x)==0 */ double xp[3],yp[3],zp[3]; double mag; int i; for(i=0;i<3;i++) zp[i] = v[i]; mag = normalize_vector(zp); if(mag==0) return(0); for(i=0;i<3;i++) R[2][i] = zp[i]; xp[0]=1; xp[1]=0; xp[2]=0; cross_prod(yp,zp,xp); /* yp = zp cross x */ mag = normalize_vector(yp); if(mag==0){ yp[1]=yp[0]=0; yp[2]=1; } for(i=0;i<3;i++) R[1][i] = yp[i]; cross_prod(xp,yp,zp); /* mag = normalize_vector(xp); this step should not be nec. */ for(i=0;i<3;i++) R[0][i] = xp[i]; return(1); }
static void form_rotation_matrix( /*******************************/ float r[4][4], vector vpn, /* View plane normal */ vector vup /* VUp vector */ ) { vector *rvects; /* 3 vectors */ int i, j; /* allocate the 3 vectors */ _new( rvects, 3 ); rvects[2] = normalize( vpn ); rvects[0] = normalize( cross_prod( vup, rvects[2] ) ); rvects[1] = cross_prod( rvects[2], rvects[0] ); identity_matrix( r ); for (i=0; i < 3; i++) { for (j=0; j < 3; j++) { r[i][j] = rvects[i].v[j]; } } /* free the 3 vectors */ _free( rvects ); }
void torque(BEMRI * b, double * t) { double F1[3] = {(X3-X1),(Y3-Y1),(Z3-Z1)} , F2[3] = {(X3-X2),(Y3-Y2),(Z3-Z2)}; double r1h = sqrt(pow((X3-X1),2) + pow((Y3-Y1),2) + pow((Z3-Z1),2)); double r2h = sqrt(pow((X3-X2),2) + pow((Y3-Y2),2) + pow((Z3-Z2),2)); double r1cm[3] = {(X4-X1),(Y4-Y1),(Z4-Z1)} , r2cm[3] = {(X4-X2),(Y4-Y2),(Z4-Z2)}; double t1[3], t2[3]; for(int ii = 0; ii < 3; ii++) { F1[ii] *= G*m1*m3/pow(r1h,3); //compute forces on each component from SMBH F2[ii] *= G*m2*m3/pow(r2h,3); } cross_prod(r1cm, F1, t1); //compute the torque from R cross F cross_prod(r2cm, F2, t2); vect_add(t1, t2, t, 3); //add the individual torques and store in t /* printf("\ntorque is:"); Vdisplay(t,3); Vdisplay(F1,3); Vdisplay(r1cm,3); Vdisplay(F2,3); Vdisplay(r2cm,3); anykey(); */ }
/// Returns signed 2 theta (signed scattering angle w.r.t. to beam direction). double DetectorInfo::signedTwoTheta(const size_t index) const { if (isMonitor(index)) throw std::logic_error( "Two theta (scattering angle) is not defined for monitors."); const auto samplePos = samplePosition(); const auto beamLine = samplePos - sourcePosition(); if (beamLine.nullVector()) { throw Kernel::Exception::InstrumentDefinitionError( "Source and sample are at same position!"); } // Get the axis defining the sign const auto &instrumentUpAxis = m_instrument->getReferenceFrame()->vecThetaSign(); const auto sampleDetVec = position(index) - samplePos; double angle = sampleDetVec.angle(beamLine); const auto cross = beamLine.cross_prod(sampleDetVec); const auto normToSurface = beamLine.cross_prod(instrumentUpAxis); if (normToSurface.scalar_prod(cross) < 0) { angle *= -1; } return angle; }
vector<Point> outerTrees(vector<Point>& points) { auto cmp = [](const Point &p1, const Point &p2) -> bool { return p1.x == p2.x ? (p1.y < p2.y) : (p1.x < p2.x); }; sort(points.begin(), points.end(), cmp); vector<Point> b, t; // bottom, top for (auto &p : points) { while (b.size() >= 2 && cross_prod(b[b.size()-2], b[b.size()-1], p) < 0) { b.pop_back(); } b.push_back(p); } for (auto &p : points) { while (t.size() >= 2 && cross_prod(t[t.size()-2], t[t.size()-1], p) > 0) { t.pop_back(); } t.push_back(p); } set<Point, decltype(cmp)> uniq(cmp); for (auto &p : b) { uniq.insert(p); } for (auto &p : t) { uniq.insert(p); } vector<Point> ans(uniq.begin(), uniq.end()); return ans; }
Matrix CoordinateSystem::getRotFromCompass(CompassData& compassData, GravityData& gravityData) { Vector compass_vector(3); compass_vector(0) = compassData.x(); compass_vector(1) = compassData.y(); compass_vector(2) = compassData.z(); Vector gravity_vector(3); gravity_vector(0) = gravityData.x(); gravity_vector(1) = gravityData.y(); gravity_vector(2) = gravityData.z(); Vector East(3); cross_prod(compass_vector, gravity_vector, East); // East = cross(compass_vector, gravity_vector) double normEast = norm_2(East); if (normEast < 0) return IdentityMatrix(3); East /= normEast; // normalization gravity_vector /= norm_2(gravity_vector); Vector North(3); cross_prod(gravity_vector, East, North); // North = cross(gravity_vector, East) Matrix rotmat(3, 3); row(rotmat, 0) = East; row(rotmat, 1) = North; row(rotmat, 2) = gravity_vector; return Matrix(rotmat); }
int lines_intersect(int i,int j,int k,int l,ls lss[MAX_LS_AMOUNT]) /* checks if two lines intersect on 3D sphere see theory in paper Pulkki, V. Lokki, T. "Creating Auditory Displays with Multiple Loudspeakers Using VBAP: A Case Study with DIVA Project" in International Conference on Auditory Displays -98. E-mail [email protected] if you want to have that paper.*/ { cart_vec v1; cart_vec v2; cart_vec v3, neg_v3; float angle; float dist_ij,dist_kl,dist_iv3,dist_jv3,dist_inv3,dist_jnv3; float dist_kv3,dist_lv3,dist_knv3,dist_lnv3; cross_prod(lss[i].coords,lss[j].coords,&v1); cross_prod(lss[k].coords,lss[l].coords,&v2); cross_prod(v1,v2,&v3); neg_v3.x= 0.0 - v3.x; neg_v3.y= 0.0 - v3.y; neg_v3.z= 0.0 - v3.z; dist_ij = (vec_angle(lss[i].coords,lss[j].coords)); dist_kl = (vec_angle(lss[k].coords,lss[l].coords)); dist_iv3 = (vec_angle(lss[i].coords,v3)); dist_jv3 = (vec_angle(v3,lss[j].coords)); dist_inv3 = (vec_angle(lss[i].coords,neg_v3)); dist_jnv3 = (vec_angle(neg_v3,lss[j].coords)); dist_kv3 = (vec_angle(lss[k].coords,v3)); dist_lv3 = (vec_angle(v3,lss[l].coords)); dist_knv3 = (vec_angle(lss[k].coords,neg_v3)); dist_lnv3 = (vec_angle(neg_v3,lss[l].coords)); /* if one of loudspeakers is close to crossing point, don't do anything*/ if(fabsf(dist_iv3) <= 0.01 || fabsf(dist_jv3) <= 0.01 || fabsf(dist_kv3) <= 0.01 || fabsf(dist_lv3) <= 0.01 || fabsf(dist_inv3) <= 0.01 || fabsf(dist_jnv3) <= 0.01 || fabsf(dist_knv3) <= 0.01 || fabsf(dist_lnv3) <= 0.01 ) return(0); if (((fabsf(dist_ij - (dist_iv3 + dist_jv3)) <= 0.01 ) && (fabsf(dist_kl - (dist_kv3 + dist_lv3)) <= 0.01)) || ((fabsf(dist_ij - (dist_inv3 + dist_jnv3)) <= 0.01) && (fabsf(dist_kl - (dist_knv3 + dist_lnv3)) <= 0.01 ))) { return (1); } else { return (0); } }
int true_anomaly(binary * b) { double x,y,z,vx,vy,vz,r,v,k,h[3],R[3],V[3],e_vec[3],vxh1[3],vxh2[3],R_temp[3],theta,edotr; int rv=1; //First translate to mass 1 rest frame x = b->x2[0] - b->x1[0]; y = b->x2[1] - b->x1[1]; z = b->x2[2] - b->x1[2]; vx = b->v2[0] - b->v1[0]; vy = b->v2[1] - b->v1[1]; vz = b->v2[2] - b->v1[2]; r = sqrt(x*x + y*y + z*z); v = sqrt(vx*vx + vy*vy + vz*vz); k = G*b->mass1 + G*b->mass2; //here k is the standard gravitational parameter G(m1 + m2) //put together vectors of r and v R[0] = x; R[1] = y; R[2] = z; V[0] = vx; V[1] = vy; V[2] = vz; //calculate vector h cross_prod(R,V,h); //calculate the eccentricity vector cross_prod(V,h,vxh1); vect_mult_scalar(vxh1, 1/k, vxh2, 3); vect_mult_scalar(R,-1/r,R_temp,3); vect_add(vxh2,R_temp,e_vec,3); //find true anomaly from r edotr = dot_prod(e_vec,R,3); theta = acos(edotr / ( mag(e_vec,3) * mag(R,3) ) ); if(dot_prod(R,V,3) < 0) { rv = 0; //printf("\nold theta = %.3f\nnew theta = %.3f\n",theta,2*PI-theta); theta = 2*PI - theta; } b->true_anomaly = theta; return rv; }
// draw triangle with per-vertex colors void POV3DisplayDevice::tricolor(const float * xyz1, const float * xyz2, const float * xyz3, const float * n1, const float * n2, const float * n3, const float *c1, const float *c2, const float *c3) { float vec1[3], vec2[3], vec3[3], norm1[3], norm2[3], norm3[3]; float leg1[3], leg2[3], trinorm[3], ang1, ang2, ang3; // transform the world coordinates (transMat.top()).multpoint3d(xyz1, vec1); (transMat.top()).multpoint3d(xyz2, vec2); (transMat.top()).multpoint3d(xyz3, vec3); // and the normals (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); // write_materials(); // Don't write degenerate triangles -- those with all normals more than 90 // degrees from triangle normal or its inverse. vec_sub(leg1, vec2, vec1); vec_sub(leg2, vec3, vec1); cross_prod(trinorm, leg1, leg2); ang1 = dot_prod(trinorm, norm1); ang2 = dot_prod(trinorm, norm2); ang3 = dot_prod(trinorm, norm3); if ( ((ang1 >= 0.0) || (ang2 >= 0.0) || (ang3 >= 0.0)) && ((ang1 <= 0.0) || (ang2 <= 0.0) || (ang3 <= 0.0)) ) { degenerate_triangles++; return; } // If all verticies have the same color, don't bother with per-vertex // coloring if ( (c1[0] == c2[0]) && (c1[0] == c3[0]) && (c1[1] == c2[1]) && (c1[1] == c3[1]) && (c1[2] == c2[2]) && (c1[2] == c3[2]) ) { fprintf(outfile, "VMD_triangle("); fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,", vec1[0], vec1[1], -vec1[2], vec2[0], vec2[1], -vec2[2], vec3[0], vec3[1], -vec3[2]); fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,", norm1[0], norm1[1], -norm1[2], norm2[0], norm2[1], -norm2[2], norm3[0], norm3[1], -norm3[2]); fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n", c1[0], c1[1], c1[2], 1 - mat_opacity); } else { fprintf(outfile, "VMD_tricolor("); fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,", vec1[0], vec1[1], -vec1[2], vec2[0], vec2[1], -vec2[2], vec3[0], vec3[1], -vec3[2]); fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,", norm1[0], norm1[1], -norm1[2], norm2[0], norm2[1], -norm2[2], norm3[0], norm3[1], -norm3[2]); fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>,rgbt<%.3f,%.3f,%.3f,%.3f>,rgbt<%.3f,%.3f,%.3f,%.3f>)\n", c1[0], c1[1], c1[2], 1 - mat_opacity, c2[0], c2[1], c2[2], 1 - mat_opacity, c3[0], c3[1], c3[2], 1 - mat_opacity); } }
int polar_cmp(Point *p1, Point *p2) { int res; double d, x1, x2, y1, y2; res = cross_prod(p1, p2, P0); if (res == CW) return -1; else if (res == CCW) return 1; else { x1 = p1->x - P0->x; x2 = p2->x - P0->x; y1 = p1->y - P0->y; y2 = p2->y - P0->y; d = ((x1*x1) + (y1*y1)) - ((x2*x2) + (y2*y2)); if (fabs(d) < EPSILON) return 0; else if (d < 0.0) return -1; else return 1; } }
void Alaska::make_normals(COMPLEX c[NX][NY]) { double x_value,y_value; x_value=MAX_WORLD_X/NX; y_value=MAX_WORLD_Y/NY; for (int i=0;i<NX-1;i++) { for (int j=0;j<NY-1;j++) { ta[0]=x_value; ta[1]=0.0; ta[2]=(c[i+1][j].real-c[i][j].real)*scale_height; tb[0]=0.0; tb[1]=y_value; tb[2]=(c[i][j+1].real-c[i][j].real)*scale_height; cross_prod(ta,tb,tc); normals[i][j][0]=tc[0]; normals[i][j][1]=tc[1]; normals[i][j][2]=tc[2]; } } for (int i=0;i<NX;i++) { normals[i][NX-1][0]=normals[i][0][0]; normals[i][NX-1][1]=normals[i][0][1]; normals[i][NX-1][2]=normals[i][0][2]; normals[NX-1][i][0]=normals[0][i][0]; normals[NX-1][i][1]=normals[0][i][1]; normals[NX-1][i][2]=normals[0][i][2]; } }
static void tile_calc_normal_hid(scene_t *s, hid_t hid) { int lvl = HID_GET_LEVEL(hid); int x = HID_GET_X_POS(hid); int y = HID_GET_Y_POS(hid); int x1, x2, y1, y2; x1 = x==0?0:x-1; y1 = y==0?0:y-1; x2 = x==(TILE_SUBTILE_HM_PER_TILE(lvl)-1)?x:x+1; y2 = y==(TILE_SUBTILE_HM_PER_TILE(lvl)-1)?y:y+1; hid_t xhid1, xhid2, yhid1, yhid2; HID_SET(xhid1, lvl, x1, y); HID_SET(xhid2, lvl, x2, y); HID_SET(yhid1, lvl, x, y1); HID_SET(yhid2, lvl, x, y2); GLfloat xv[3], yv[3], normal[3]; xv[0] = scene_hid_x_coord(s, xhid1)- scene_hid_x_coord(s, xhid2); xv[1] = 0.0; xv[2] = scene_hid_lookup(s, xhid1)->height - scene_hid_lookup(s,xhid2)->height; yv[0] = 0.0; yv[1] = scene_hid_y_coord(s, yhid1)- scene_hid_y_coord(s, yhid2); yv[2] = scene_hid_lookup(s, yhid1)->height - scene_hid_lookup(s,yhid2)->height; cross_prod(xv, yv, normal); normalize(normal, normal, 3); heightmap_element_t *he = scene_hid_lookup(s, hid); memcpy(he->normal, normal, sizeof(GLfloat)*3); //printf("Normal is %f %f %f\n", normal[0], normal[1], normal[2]); }
// draw a cylinder void X3DDisplayDevice::cylinder_noxfrm(float *ta, float *tb, float radius, int filled) { if (ta[0] == tb[0] && ta[1] == tb[1] && ta[2] == tb[2]) { return; // we don't serve your kind here } float height = distance(ta, tb); fprintf(outfile, "<Transform translation='%g %g %g' ", ta[0], ta[1] + (height / 2.0), ta[2]); float rotaxis[3]; float cylaxdir[3]; float yaxis[3] = {0.0, 1.0, 0.0}; vec_sub(cylaxdir, tb, ta); vec_normalize(cylaxdir); float dp = dot_prod(yaxis, cylaxdir); cross_prod(rotaxis, cylaxdir, yaxis); vec_normalize(rotaxis); // if we have decent rotation vector, use it if ((rotaxis[0]*rotaxis[0] + rotaxis[1]*rotaxis[1] + rotaxis[2]*rotaxis[2]) > 0.5) { fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); fprintf(outfile, "rotation='%g %g %g %g'", rotaxis[0], rotaxis[1], rotaxis[2], -acos(dp)); } else if (dp < -0.98) { // if we have denormalized rotation vector, we can assume it is // caused by a cylinder axis that is nearly coaxial with the Y axis. // If this is the case, we either perform no rotation in the case of a // angle cosine near 1.0, or a 180 degree rotation for a cosine near -1. fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); fprintf(outfile, "rotation='0 0 -1 -3.14159'"); } fprintf(outfile, ">\n"); fprintf(outfile, " <Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); // draw the cylinder fprintf(outfile, " <Cylinder " "bottom='%s' height='%g' radius='%g' side='%s' top='%s' />\n", filled ? "true" : "false", height, radius, "true", filled ? "true" : "false"); fprintf(outfile, " </Shape>\n"); fprintf(outfile, "</Transform>\n"); }
void calc_total_angular_momentum(BEMRI * b) { double p1[3],p2[3],p3[3],l1[3],l2[3],l3[3],temp[3]; (*b).L = 0; vect_mult_scalar(V1,m1,p1,3); vect_mult_scalar(V2,m2,p2,3); vect_mult_scalar(V3,m3,p3,3); cross_prod(R1,p1,l1); cross_prod(R2,p2,l2); cross_prod(R3,p3,l3); vect_add(l1,l2,temp,3); vect_add(l3,temp,temp,3); (*b).L = mag(temp,3); return; }
template<> Math::Quaternion calculate< Math::Vector< double, 3 > >( Math::Vector< double, 3 >& orig, Math::Pose& pose1, Math::Vector< double, 3 >& pos2 ) { Math::Vector< double, 3 > dir = (~pose1) * pos2; dir = dir / ublas::norm_2( dir ); Math::Vector< double, 3 > axis = cross_prod( orig, dir ); Math::Quaternion q( axis[0], axis[1], axis[2], 1 + ublas::inner_prod( orig, dir ) ); q.normalize(); return pose1.rotation() * q; }
// put in new data, and put the command void DispCmdTriangle::putdata(const float *p1, const float *p2, const float *p3, VMDDisplayList *dobj) { int i; float tmp1[3], tmp2[3], tmp3[3]; // precompute the normal for for (i=0; i<3; i++) { // faster drawings later tmp1[i] = p2[i] - p1[i]; tmp2[i] = p3[i] - p2[i]; } cross_prod( tmp3, tmp1, tmp2); vec_normalize(tmp3); set_array(p1, p2, p3, tmp3, tmp3, tmp3, dobj); }
int convex_hull(Point *poly, int n, Point *hull) { int i, min, h; if (n < 1) return 0; min = 0; P0 = &hull[0]; *P0 = poly[0]; for (i = 1; i < n; i++) { if ((poly[i].y < P0->y) || ((poly[i].y == P0->y) && (poly[i].x < P0->x))) { min = i; *P0 = poly[i]; } } poly[min] = poly[0]; poly[0] = *P0; h = 1; if (n == 1) return h; qsort(poly+1, n-1, sizeof(poly[1]), (int (*)(const void *, const void *))polar_cmp); for (i = 1; i < n; i++) { if ((fabs(poly[i].x - hull[0].x) > EPSILON) || (fabs(poly[i].y - hull[0].y) > EPSILON)) { break; } } if (i == n) return h; hull[h++] = poly[i++]; for ( ; i < n; i++) { while ((h > 1) && (cross_prod(&poly[i], &hull[h-1], &hull[h-2]) != CCW)) { h--; } hull[h++] = poly[i]; } return h; }
/** * Establish the first surface normal. Tries to establish normal from * non-colinear points * @param vertices : All vertices * @return surface normal, or 0,0,0 if not found */ Kernel::V3D surfaceNormal(const std::vector<Kernel::V3D> &vertices) { auto v0 = vertices[1] - vertices[0]; Kernel::V3D normal{0, 0, 0}; const static double tolerance_sq = std::pow(1e-9, 2); // Look for normal amongst first 3 non-colinear points for (size_t i = 1; i < vertices.size() - 1; ++i) { auto v1 = vertices[i + 1] - vertices[i]; normal = v0.cross_prod(v1); if (normal.norm2() > tolerance_sq) { break; } } return normal; }
bool GeometryUtilities::spansPlane(const cv::Vec3d &x, const cv::Vec3d &y, const cv::Vec3d &z) { // compute direction vectors y-x, z-x cv::Vec3d d1(y[0] - x[0], y[1] - x[1], y[2] - x[2]); cv::Vec3d d2(z[0] - x[0], z[1] - x[1], z[2] - x[2]); // cross-product between these vectors is zero length? points are colinear -> no plane cv::Vec3d cross_prod(d1[1]*d2[2] - d2[1]*d1[2], d1[0]*d2[2] - d2[0]*d1[2], d1[0]*d2[1] - d2[0]*d1[1]); if ((cross_prod[0]*cross_prod[0] + cross_prod[1]*cross_prod[1] + cross_prod[2]*cross_prod[2]) <= std::numeric_limits<double>::epsilon()) { return false; } return true; }
void X3DDisplayDevice::cone(float *a, float *b, float r) { float ta[3], tb[3], radius; if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) { return; // we don't serve your kind here } // transform the coordinates (transMat.top()).multpoint3d(a, ta); (transMat.top()).multpoint3d(b, tb); radius = scale_radius(r); float height = distance(a, b); fprintf(outfile, "<Transform translation='%g %g %g' ", ta[0], ta[1] + (height / 2.0), ta[2]); float rotaxis[3]; float cylaxdir[3]; float yaxis[3] = {0.0, 1.0, 0.0}; vec_sub(cylaxdir, tb, ta); vec_normalize(cylaxdir); float dp = dot_prod(yaxis, cylaxdir); cross_prod(rotaxis, cylaxdir, yaxis); vec_normalize(rotaxis); if ((rotaxis[0]*rotaxis[0] + rotaxis[1]*rotaxis[1] + rotaxis[2]*rotaxis[2]) > 0.5) { fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); fprintf(outfile, "rotation='%g %g %g %g'", rotaxis[0], rotaxis[1], rotaxis[2], -acos(dp)); } fprintf(outfile, ">\n"); fprintf(outfile, " <Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); // draw the cone fprintf(outfile, " <Cone bottomRadius='%g' height='%g'/>\n", radius, height); fprintf(outfile, " </Shape>\n"); fprintf(outfile, "</Transform>\n"); }
float vol_p_side_lgth(int i, int j,int k, ls lss[MAX_LS_AMOUNT] ){ /* calculate volume of the parallelepiped defined by the loudspeaker direction vectors and divide it with total length of the triangle sides. This is used when removing too narrow triangles. */ float volper, lgth; cart_vec xprod; cross_prod(lss[i].coords, lss[j].coords, &xprod); volper = fabsf(vec_prod(xprod, lss[k].coords)); lgth = (fabsf(vec_angle(lss[i].coords,lss[j].coords)) + fabsf(vec_angle(lss[i].coords,lss[k].coords)) + fabsf(vec_angle(lss[j].coords,lss[k].coords))); if(lgth>0.00001) return volper / lgth; else return 0.0; }
/* Calculate volume of a tet_mesh by summing the volumes of all tets. Volume of each tet is given by: (1/6) * abs(dot_prod(a,cross_prod(b,c))) where a, b, and c are three edges of the tet that share a common vertex of the tet. */ double meshvol(struct tet_mesh *tet_mesh) { struct node **nodes; struct tet_list *tlp; struct tet *tp; struct vector3 p1,p2,a,b,c,bxc; double volume; nodes=tet_mesh->nodes; volume = 0.0; for (tlp=tet_mesh->tet_head; tlp!=NULL; tlp=tlp->next) { tp=tlp->tet; p1.x=nodes[tp->node_index[0]]->x; p1.y=nodes[tp->node_index[0]]->y; p1.z=nodes[tp->node_index[0]]->z; p2.x=nodes[tp->node_index[1]]->x; p2.y=nodes[tp->node_index[1]]->y; p2.z=nodes[tp->node_index[1]]->z; vectorize(&p1,&p2,&a); p2.x=nodes[tp->node_index[2]]->x; p2.y=nodes[tp->node_index[2]]->y; p2.z=nodes[tp->node_index[2]]->z; vectorize(&p1,&p2,&b); p2.x=nodes[tp->node_index[3]]->x; p2.y=nodes[tp->node_index[3]]->y; p2.z=nodes[tp->node_index[3]]->z; vectorize(&p1,&p2,&c); cross_prod(&b,&c,&bxc); volume += fabs(dot_prod(&a,&bxc)); } volume = volume/6.0; return(volume); }
// draw a square, given 3 of four points void DispCmdSquare::putdata(float *p1, float *p2,float *p3,VMDDisplayList *dobj) { DispCmdSquare *ptr = (DispCmdSquare *)(dobj->append(DSQUARE, sizeof(DispCmdSquare))); if (ptr == NULL) return; int i; float tmp1[3], tmp2[3]; // precompute the normal for for (i=0; i<3; i++) { // faster drawings later tmp1[i] = p2[i] - p1[i]; tmp2[i] = p3[i] - p2[i]; } cross_prod( ptr->norml, tmp1, tmp2); vec_normalize(ptr->norml); memcpy(ptr->pos1,p1,3*sizeof(float)); memcpy(ptr->pos2,p2,3*sizeof(float)); memcpy(ptr->pos3,p3,3*sizeof(float)); for (i=0; i<3; i++) ptr->pos4[i] = p1[i] + tmp2[i]; // compute the fourth point }
int solid_chopper(Solid_List s, Plane_List p) { Face_PointerList faceCurs; Seg_PointerList segCurs; Face newFace; Seg_PointerList tmpListSeg, tmpListSegHead, tmpListSeg2,tmpListSeg2old, tmp,tmp2; // lista per salvare man mano che li trovo i segmenti int int, per poi ordinare! int adiacenti = 0, trovato_adiacenti=0 , trovato_primo_seg=0; Point V1,V2,V3; // punti per fare i calcoli sul verso double proiezione; char invertito; Face_PointerList newFaceList, newFaceListHead, oldFaceList; Solid newSol; faceCurs = s->So.f; // assegno la lista facce tmpListSegHead = (Seg_PointerList) malloc (sizeof(Seg_PointerList_El)); tmpListSeg = tmpListSegHead; while (faceCurs != NULL &&!trovato_primo_seg) // primo caso in un ciclo while a parte { if (faceCurs->fptr->side == 2) // se è di tipo intersezione, ma solo fra quelle sotto! (per non trovarle due volte) { // devo scorrere i segmenti della faccia fino a trovarne uno di tipo int - int segCurs = faceCurs->fptr->s; while (segCurs != NULL && !(segCurs->sptr->A->side == '0' && segCurs->sptr->B->side == '0')) { segCurs = segCurs->next; // scorro avanti } if (segCurs != NULL) { trovato_primo_seg=1; tmpListSeg->sptr = segCurs->sptr; // salvo faceCurs = faceCurs->next; // scorri avanti la lista facce } } if(!trovato_primo_seg){ faceCurs = faceCurs->next; // scorri avanti la lista facce } } // fine del primo caso while (faceCurs != NULL) // tutti gli altri casi { if (faceCurs->fptr->side == 2) // guardiamo solo quelle sotto perchè quelle sopra trovano gli stessi segmenti { // devo scorrere i segmenti della faccia fino a trovarne uno di tipo int - int segCurs = faceCurs->fptr->s; while (segCurs != NULL && !(segCurs->sptr->A->side == '0' && segCurs->sptr->B->side == '0')) { segCurs = segCurs->next; // scorro avanti } if (segCurs != NULL) { tmpListSeg->next = (Seg_PointerList) malloc (sizeof(Seg_PointerList_El)); // alloco il next tmpListSeg = tmpListSeg->next; // scorro avanti tmpListSeg->sptr = segCurs->sptr; // salvo il segmento } } faceCurs = faceCurs->next; // avanti con le facce } tmpListSeg->next = NULL; /* a questo punto ho in tmpListSegHead una lista di tutti i segmenti di tipo int int, però DISORDINATI devo ordinarli in modo adiacente e antiorario rispetto al vettore normale: Prima li ordiniamo in modo adiacente ma in verso come viene, poi facciamo il cross tra due consecutivi, e vediamo se è concorde o discorde alla normale alla faccia: se lo è bene, se no INVERTIAMO IL VETTORE NORMALE, e tenendone conto per decidere interni ed esterni, ovvero: CASO 1 NON SI CAMBIA => il solido S1 formato da facce + ha il vettore entrante, e viceversa CASO 2 SI INVERTE IL VETTORE => il solido fatto da facce + ha il vettore uscente, e viceversa; */ tmpListSeg = tmpListSegHead; tmpListSeg2old=tmpListSegHead; tmpListSeg2 = tmpListSegHead->next; if (tmpListSeg2 == NULL){ return 1; } while (tmpListSeg->next!= NULL) { while (tmpListSeg2 != NULL && !trovato_adiacenti) // qui la condizione è inutile perchè lo deve trovare sempre! se arriva a null c'è un errore { adiacenti = ((tmpListSeg2->sptr->A == tmpListSeg->sptr->A) || (tmpListSeg2->sptr->A == tmpListSeg->sptr->B) || (tmpListSeg2->sptr->B == tmpListSeg->sptr->A) || (tmpListSeg2->sptr->B == tmpListSeg->sptr->B)); if (adiacenti) { trovato_adiacenti=1; // tmplistseg2 va subito dopo tmplistseg if(tmpListSeg2!=tmpListSeg->next){ tmp = tmpListSeg->next; tmp2=tmpListSeg2->next; tmpListSeg->next = tmpListSeg2; tmpListSeg2->next=tmp; tmpListSeg2old->next=tmp2; } // l'orientamento lo vediamo dopo! tmpListSeg = tmpListSeg->next; // sistemo i cursori nelle posizioni per il prossimo run if (tmpListSeg->next != NULL) // se non sono arrivato a fine lista { tmpListSeg2 = tmpListSeg->next; tmpListSeg2old=tmpListSeg; } } if(!trovato_adiacenti){ tmpListSeg2old=tmpListSeg2; tmpListSeg2 = tmpListSeg2->next; // scorro avanti se non l'ha trovato } } trovato_adiacenti=0; } // ora abbiamo la lista coi segmenti adiacenti, ma non ancora ordinati in verso! tmpListSeg = tmpListSegHead; tmpListSeg2 = tmpListSegHead->next; // riporto i cursori al primo e secondo posto if (tmpListSeg->sptr->A == tmpListSeg2->sptr->A) //vedi disegno su faiscbuk! { tmpListSeg->orient = '-'; // il primo è meno tmpListSeg2->orient = '+'; // il secondo è + } else if (tmpListSeg->sptr->A == tmpListSeg2->sptr->B) { tmpListSeg->orient = '-'; // il primo è meno tmpListSeg2->orient = '-'; // il secondo è - } else if (tmpListSeg->sptr->B == tmpListSeg2->sptr->A) { tmpListSeg->orient = '+'; // il primo è + tmpListSeg2->orient = '+'; // il secondo è + } else if (tmpListSeg->sptr->B == tmpListSeg2->sptr->B) { tmpListSeg->orient = '+'; // il primo è + tmpListSeg2->orient = '-'; // il secondo è - } // ho sistemato l'ordine dei primi 2 segmenti, ora faccio tutti gli altri while (tmpListSeg2->next != NULL) { if (tmpListSeg2->orient == '+') { if (tmpListSeg2->sptr->B == tmpListSeg2->next->sptr->A) { // il successivo è concorde tmpListSeg2->next->orient = '+'; } else { // il successivo è discorde tmpListSeg2->next->orient = '-'; } } else /* if (tmpListSeg2->orient == '-') */ { if (tmpListSeg2->sptr->A == tmpListSeg2->next->sptr->A) { // il successivo è concorde tmpListSeg2->next->orient = '+'; } else { // il successivo è discorce tmpListSeg2->next->orient = '-'; } } tmpListSeg2 = tmpListSeg2->next; // scorro avanti } // fine ciclo di ordinamento // ora ho i segmenti della mia nuova faccia, salvati adiacenti e ordinati in tmpListSegHead! // ora devo capire se sono orarie o antiorarie rispetto al versore uscente tmpListSeg = tmpListSegHead; // calcolo i vettori dei primi due segmenti, tenendo conto dell'ordine! if (tmpListSeg->orient == '+') { V1.x = tmpListSeg->sptr->B->x - tmpListSeg->sptr->A->x; V1.y = tmpListSeg->sptr->B->y - tmpListSeg->sptr->A->y; V1.z = tmpListSeg->sptr->B->z - tmpListSeg->sptr->A->z; } else { V1.x = tmpListSeg->sptr->A->x - tmpListSeg->sptr->B->x; V1.y = tmpListSeg->sptr->A->y - tmpListSeg->sptr->B->y; V1.z = tmpListSeg->sptr->A->z - tmpListSeg->sptr->B->z; } tmpListSeg = tmpListSeg->next; if (tmpListSeg->orient == '+') { V2.x = tmpListSeg->sptr->B->x - tmpListSeg->sptr->A->x; V2.y = tmpListSeg->sptr->B->y - tmpListSeg->sptr->A->y; V2.z = tmpListSeg->sptr->B->z - tmpListSeg->sptr->A->z; } else { V2.x = tmpListSeg->sptr->A->x - tmpListSeg->sptr->B->x; V2.y = tmpListSeg->sptr->A->y - tmpListSeg->sptr->B->y; V2.z = tmpListSeg->sptr->A->z - tmpListSeg->sptr->B->z; } //ora ho i due vettori dei primi due segmenti V3 = cross_prod(V1,V2); // prodotto vettore #ifdef DEBUG_ if (abs(eu_norm(V3)) < tol) { fprintf(OUTPUT, "OCHO! I due vettori sono un po' troppo paralleli! \n"); } #endif V3 = vett_scal(V3 , 1/eu_norm(V3)); // normalizzo V3 proiezione = dot_prod(V3 , p->pl.n); if ( proiezione > tol ) // maggiore della tolleranza { newFace.norm_vect.x = p->pl.n.x; // copio il vettore normale del piano nella nuova faccia SENZA INVERTIRE newFace.norm_vect.y = p->pl.n.y; newFace.norm_vect.z = p->pl.n.z; invertito = 0; } else if (proiezione < -tol) { newFace.norm_vect.x = -(p->pl.n.x); // copio il vettore normale del piano nella nuova faccia INVERTENDOLO newFace.norm_vect.y = -(p->pl.n.y); newFace.norm_vect.z = -(p->pl.n.z); invertito = 1; } #ifdef DEBUG_ else { fprintf(OUTPUT, "OCHO! I due vettori sono un po' troppo paralleli! \n"); } #endif newFace.s = tmpListSegHead; // assegno la lista di segmenti, che ora è ordinata, adiacente e antioraria rispetto al vettore normale newFace.side = 0; Face_add_head(newFace,Fc,&Fc); // aggiungo la nuova faccia in testa alla lista NUMFACCE++; //ai segmenti della faccia nuova devo aggiungere la faccia in head nella propria face_pointerlist f segCurs = Fc->F.s; while(segCurs!=NULL){ faceCurs=segCurs->sptr->f; segCurs->sptr->f = (Face_PointerList) malloc(sizeof(Face_PointerList_El)); segCurs->sptr->f->fptr= &(Fc->F); segCurs->sptr->f->next=faceCurs; segCurs=segCurs->next; } // aggiungo la nuova faccia al solido attuale CHE DECIDO ESSERE QUELLO CON I PUNTI + newFaceList = s->So.f; // salvo tmp la lista facce s->So.f = (Face_PointerList) malloc(sizeof(Face_PointerList_El)); // alloco s->So.f->fptr = &(Fc->F) ; //aggiungo la nuova faccia s->So.f->next = newFaceList; // accodo il resto della lista if (invertito) // conto di sovrascrivere il solido con i + { s->So.f->orient = '+'; // è uscente } else { s->So.f->orient = '-'; // è entrante } newFaceListHead = (Face_PointerList) malloc(sizeof(Face_PointerList_El)); // alloco PER LA FACCIA COI - newFaceList = newFaceListHead; // assegno il cursore newFaceList->fptr = &(Fc->F); // Copio la faccia nuova nel nuovo solido if (invertito) { newFaceList->orient = '-'; // è entrante } else { newFaceList->orient = '+'; // è uscente } newFaceList->next = NULL; Solid_add_head(newSol, Sol, &Sol); // ho aggiunto il nuovo solido in testa NUMSOL++; Fc->F.Sol1 = &(s->So); // sistemo i puntatori a solido della faccia nuova Fc->F.Sol2 = &(Sol->So); // ora devo dividere la lista originale in due a seconda che siano + o - oldFaceList = s->So.f; // assegno la prima vecchia faccia while (oldFaceList->next != NULL) // finchè non arrivo all'ultimo prima di NULL { if (oldFaceList->next->fptr->side == 2 || oldFaceList->next->fptr->side == 1) // se la faccia è - o - intersezione devo spostarla nella lista nuova { newFaceList->next = (Face_PointerList) malloc(sizeof(Face_PointerList_El)); newFaceList->next = oldFaceList->next; newFaceList = newFaceList->next; // scorro avanti la nuova lista oldFaceList->next = oldFaceList->next->next; // cucio le due estremità della lista newFaceList->next = NULL; // termino la lista nuova // ora vado a modificare i puntatori a solido della faccia che ho spostato nella lista nuova if (newFaceList->fptr->Sol1 == &(s->So)) // se era salvato come il primo solido modifico questo { newFaceList->fptr->Sol1 = &(Sol->So); } else // se invece era Sol2 il solido che sto modificando, allora modifico quello (non faccio altri controlli) { newFaceList->fptr->Sol2 = &(Sol->So); } } else { oldFaceList = oldFaceList->next; } } // adesso ho le due liste divise per facce di tipo sx e dx,con la faccia nuova in comune // assegno la lista - al nuovo solido Sol->So.f = newFaceListHead; return 0; }
static void spread_it(t_rvbap *x, t_float *final_gs) // apply the sound signal to multiple panning directions // that causes some spreading. // See theory in paper V. Pulkki "Uniform spreading of amplitude panned // virtual sources" in WASPAA 99 { t_float vscartdir[3]; t_float spreaddir[16][3]; t_float spreadbase[16][3]; long i, spreaddirnum; t_float power; if(x->x_dimension == 3){ spreaddirnum=16; angle_to_cart(x->x_azi,x->x_ele,vscartdir); new_spread_dir(x, spreaddir[0], vscartdir, x->x_spread_base); new_spread_base(x, spreaddir[0], vscartdir); cross_prod(x->x_spread_base, vscartdir, spreadbase[1]); // four orthogonal dirs cross_prod(spreadbase[1], vscartdir, spreadbase[2]); cross_prod(spreadbase[2], vscartdir, spreadbase[3]); // four between them for(i=0;i<3;i++) spreadbase[4][i] = (x->x_spread_base[i] + spreadbase[1][i]) / 2.0; for(i=0;i<3;i++) spreadbase[5][i] = (spreadbase[1][i] + spreadbase[2][i]) / 2.0; for(i=0;i<3;i++) spreadbase[6][i] = (spreadbase[2][i] + spreadbase[3][i]) / 2.0; for(i=0;i<3;i++) spreadbase[7][i] = (spreadbase[3][i] + x->x_spread_base[i]) / 2.0; // four at half spreadangle for(i=0;i<3;i++) spreadbase[8][i] = (vscartdir[i] + x->x_spread_base[i]) / 2.0; for(i=0;i<3;i++) spreadbase[9][i] = (vscartdir[i] + spreadbase[1][i]) / 2.0; for(i=0;i<3;i++) spreadbase[10][i] = (vscartdir[i] + spreadbase[2][i]) / 2.0; for(i=0;i<3;i++) spreadbase[11][i] = (vscartdir[i] + spreadbase[3][i]) / 2.0; // four at quarter spreadangle for(i=0;i<3;i++) spreadbase[12][i] = (vscartdir[i] + spreadbase[8][i]) / 2.0; for(i=0;i<3;i++) spreadbase[13][i] = (vscartdir[i] + spreadbase[9][i]) / 2.0; for(i=0;i<3;i++) spreadbase[14][i] = (vscartdir[i] + spreadbase[10][i]) / 2.0; for(i=0;i<3;i++) spreadbase[15][i] = (vscartdir[i] + spreadbase[11][i]) / 2.0; additive_vbap(final_gs,spreaddir[0],x); for(i=1;i<spreaddirnum;i++){ new_spread_dir(x, spreaddir[i], vscartdir, spreadbase[i]); additive_vbap(final_gs,spreaddir[i],x); } } else if (x->x_dimension == 2) { spreaddirnum=6; angle_to_cart(x->x_azi - x->x_spread, 0, spreaddir[0]); angle_to_cart(x->x_azi - x->x_spread/2, 0, spreaddir[1]); angle_to_cart(x->x_azi - x->x_spread/4, 0, spreaddir[2]); angle_to_cart(x->x_azi + x->x_spread/4, 0, spreaddir[3]); angle_to_cart(x->x_azi + x->x_spread/2, 0, spreaddir[4]); angle_to_cart(x->x_azi + x->x_spread, 0, spreaddir[5]); for(i=0;i<spreaddirnum;i++) additive_vbap(final_gs,spreaddir[i],x); } else return; if(x->x_spread > 70) for(i=0;i<x->x_ls_amount;i++){ final_gs[i] += (x->x_spread - 70) / 30.0 * (x->x_spread - 70) / 30.0 * 10.0; } for(i=0,power=0.0;i<x->x_ls_amount;i++){ power += final_gs[i] * final_gs[i]; } power = sqrt(power); for(i=0;i<x->x_ls_amount;i++){ final_gs[i] /= power; } }
void PSDisplayDevice::cylinder_approx(float *a, float *b, float r, int res, int filled) { float axis[3]; float perp1[3], perp2[3]; float pt1[3], pt2[3]; float cent[3]; float theta, theta_inc; float my_sin, my_cos; float w[3], x[3], y[3], z[3]; int n; DepthSortObject cyl_body, cyl_trailcap, cyl_leadcap; // check against degenerate cylinder if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) return; if (r <= 0) return; // first we compute the axis of the cylinder axis[0] = b[0] - a[0]; axis[1] = b[1] - a[1]; axis[2] = b[2] - a[2]; vec_normalize(axis); // now we compute some arbitrary perpendicular to that axis if ((ABS(axis[0]) < ABS(axis[1])) && (ABS(axis[0]) < ABS(axis[2]))) { perp1[0] = 0; perp1[1] = axis[2]; perp1[2] = -axis[1]; } else if ((ABS(axis[1]) < ABS(axis[2]))) { perp1[0] = -axis[2]; perp1[1] = 0; perp1[2] = axis[0]; } else { perp1[0] = axis[1]; perp1[1] = -axis[0]; perp1[2] = 0; } vec_normalize(perp1); // now we compute another vector perpendicular both to the // cylinder's axis and to the perpendicular we just found. cross_prod(perp2, axis, perp1); // initialize some stuff in the depth sort objects cyl_body.npoints = 4; cyl_body.color = colorIndex; if (filled & CYLINDER_TRAILINGCAP) { cyl_trailcap.npoints = 3; cyl_trailcap.color = colorIndex; } if (filled & CYLINDER_LEADINGCAP) { cyl_leadcap.npoints = 3; cyl_leadcap.color = colorIndex; } // we will start out with the point defined by perp2 pt1[0] = r * perp2[0]; pt1[1] = r * perp2[1]; pt1[2] = r * perp2[2]; theta = 0; theta_inc = (float) (VMD_TWOPI / res); for (n = 1; n <= res; n++) { // save the last point memcpy(pt2, pt1, sizeof(float) * 3); // increment the angle and compute new points theta += theta_inc; my_sin = (float) sin(theta); my_cos = (float) cos(theta); // compute the new points pt1[0] = r * (perp2[0] * my_cos + perp1[0] * my_sin); pt1[1] = r * (perp2[1] * my_cos + perp1[1] * my_sin); pt1[2] = r * (perp2[2] * my_cos + perp1[2] * my_sin); cyl_body.points = (float *) malloc(sizeof(float) * 8); cyl_trailcap.points = (float *) malloc(sizeof(float) * 6); cyl_leadcap.points = (float *) malloc(sizeof(float) * 6); if (!(cyl_body.points && cyl_trailcap.points && cyl_leadcap.points)) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } continue; } // we have to translate them back to their original point... w[0] = pt1[0] + a[0]; w[1] = pt1[1] + a[1]; w[2] = pt1[2] + a[2]; x[0] = pt2[0] + a[0]; x[1] = pt2[1] + a[1]; x[2] = pt2[2] + a[2]; y[0] = pt2[0] + b[0]; y[1] = pt2[1] + b[1]; y[2] = pt2[2] + b[2]; z[0] = pt1[0] + b[0]; z[1] = pt1[1] + b[1]; z[2] = pt1[2] + b[2]; memcpy(cyl_body.points, w, sizeof(float) * 2); memcpy(&cyl_body.points[2], x, sizeof(float) * 2); memcpy(&cyl_body.points[4], y, sizeof(float) * 2); memcpy(&cyl_body.points[6], z, sizeof(float) * 2); // finally, we have to compute the centerpoint of this cylinder... // we can make a slight optimization here since we know the // cylinder will be a parellelogram. we only need to average // 2 corner points to find the center. cent[0] = (w[0] + y[0]) / 2; cent[1] = (w[1] + y[1]) / 2; cent[2] = (w[2] + y[2]) / 2; cyl_body.dist = compute_dist(cent); // and finally the light scale cyl_body.light_scale = compute_light(w, x, y); // go ahead and add this to our depth-sort list memusage += sizeof(float) * 2 * cyl_body.npoints; points += cyl_body.npoints; objects++; depth_list.append(cyl_body); // Now do the same thing for the trailing end cap... if (filled & CYLINDER_TRAILINGCAP) { memcpy(&cyl_trailcap.points[0], x, sizeof(float) * 2); memcpy(&cyl_trailcap.points[2], w, sizeof(float) * 2); memcpy(&cyl_trailcap.points[4], a, sizeof(float) * 2); // finally, we have to compute the centerpoint of the triangle cent[0] = (x[0] + w[0] + a[0]) / 3; cent[1] = (x[1] + w[1] + a[1]) / 3; cent[2] = (x[2] + w[2] + a[2]) / 3; cyl_trailcap.dist = compute_dist(cent); // and finally the light scale cyl_trailcap.light_scale = compute_light(x, w, a); memusage += sizeof(float) * 2 * cyl_trailcap.npoints; points += cyl_trailcap.npoints; objects++; depth_list.append(cyl_trailcap); } // ...and the leading end cap. if (filled & CYLINDER_LEADINGCAP) { memcpy(cyl_leadcap.points, z, sizeof(float) * 2); memcpy(&cyl_leadcap.points[2], y, sizeof(float) * 2); memcpy(&cyl_leadcap.points[4], b, sizeof(float) * 2); // finally, we have to compute the centerpoint of the triangle cent[0] = (z[0] + y[0] + b[0]) / 3; cent[1] = (z[1] + y[1] + b[1]) / 3; cent[2] = (z[2] + y[2] + b[2]) / 3; cyl_leadcap.dist = compute_dist(cent); // and finally the light scale cyl_leadcap.light_scale = compute_light(z, y, b); memusage += sizeof(float) * 2 * cyl_leadcap.npoints; points += cyl_leadcap.npoints; objects++; depth_list.append(cyl_leadcap); } } }
void PSDisplayDevice::cone_approx(float *a, float *b, float r) { // XXX add ability to change number of triangles const int tris = 20; float axis[3]; float perp1[3], perp2[3]; float pt1[3], pt2[3]; float cent[3]; float x[3], y[3], z[3]; float theta, theta_inc; float my_sin, my_cos; int n; DepthSortObject depth_obj; // check against degenerate cone if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) return; if (r <= 0) return; // first we compute the axis of the cone axis[0] = b[0] - a[0]; axis[1] = b[1] - a[1]; axis[2] = b[2] - a[2]; vec_normalize(axis); // now we compute some arbitrary perpendicular to that axis if ((ABS(axis[0]) < ABS(axis[1])) && (ABS(axis[0]) < ABS(axis[2]))) { perp1[0] = 0; perp1[1] = axis[2]; perp1[2] = -axis[1]; } else if ((ABS(axis[1]) < ABS(axis[2]))) { perp1[0] = -axis[2]; perp1[1] = 0; perp1[2] = axis[0]; } else { perp1[0] = axis[1]; perp1[1] = -axis[0]; perp1[2] = 0; } vec_normalize(perp1); // now we compute another vector perpendicular both to the // cone's axis and to the perpendicular we just found. cross_prod(perp2, axis, perp1); // initialize some stuff in the depth sort object depth_obj.npoints = 3; depth_obj.color = colorIndex; // we will start out with the point defined by perp2 pt1[0] = r * perp2[0]; pt1[1] = r * perp2[1]; pt1[2] = r * perp2[2]; theta = 0; theta_inc = (float) (VMD_TWOPI / tris); for (n = 1; n <= tris; n++) { // save the last point memcpy(pt2, pt1, sizeof(float) * 3); // increment the angle and compute new points theta += theta_inc; my_sin = (float) sin(theta); my_cos = (float) cos(theta); // compute the new points pt1[0] = r * (perp2[0] * my_cos + perp1[0] * my_sin); pt1[1] = r * (perp2[1] * my_cos + perp1[1] * my_sin); pt1[2] = r * (perp2[2] * my_cos + perp1[2] * my_sin); depth_obj.points = (float *) malloc(sizeof(float) * 6); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } continue; } // we have to translate them back to their original point... x[0] = pt1[0] + a[0]; x[1] = pt1[1] + a[1]; x[2] = pt1[2] + a[2]; y[0] = pt2[0] + a[0]; y[1] = pt2[1] + a[1]; y[2] = pt2[2] + a[2]; // now we use the apex of the cone as the third point z[0] = b[0]; z[1] = b[1]; z[2] = b[2]; memcpy(depth_obj.points, x, sizeof(float) * 2); memcpy(&depth_obj.points[2], y, sizeof(float) * 2); memcpy(&depth_obj.points[4], z, sizeof(float) * 2); // finally, we have to compute the centerpoint of this // triangle... cent[0] = (x[0] + y[0] + z[0]) / 3; cent[1] = (x[1] + y[1] + z[1]) / 3; cent[2] = (x[2] + y[2] + z[2]) / 3; depth_obj.dist = compute_dist(cent); // and the light shading factor depth_obj.light_scale = compute_light(x, y, z); // go ahead and add this to our depth-sort list memusage += sizeof(float) * 2 * depth_obj.npoints; points += depth_obj.npoints; objects++; depth_list.append(depth_obj); } }
void DispCmdCylinder::putdata(const float *pos1, const float *pos2, float rad, int res, int filled, VMDDisplayList *dobj) { float lenaxis[3]; vec_sub(lenaxis, pos1, pos2); // check that it's valid if (dot_prod(lenaxis,lenaxis) == 0.0 || res <= 0) return; if (lastres != res ) { rot[0] = cosf( (float) VMD_TWOPI / (float) res); rot[1] = sinf( (float) VMD_TWOPI / (float) res); } lastres = res; size_t size = (9 + res*3*3)*sizeof(float); float *pos = (float *)(dobj->append(DCYLINDER, size)); if (pos == NULL) return; memcpy(pos,pos1,3*sizeof(float)); memcpy(pos+3,pos2,3*sizeof(float)); pos[6] = rad; pos[7] = (float)res; pos[8] = (float)filled; float axis[3]; vec_sub(axis, pos1, pos2); vec_normalize(axis); int i; // find an axis not aligned with the cylinder if (fabs(axis[0]) < fabs(axis[1]) && fabs(axis[0]) < fabs(axis[2])) { i = 0; } else if (fabs(axis[1]) < fabs(axis[2])) { i = 1; } else { i = 2; } float perp[3]; perp[i] = 0; // this is not aligned with the cylinder perp[(i+1)%3] = axis[(i+2)%3]; perp[(i+2)%3] = -axis[(i+1)%3]; vec_normalize(perp); float perp2[3]; cross_prod(perp2, axis, perp); // find a normal to the cylinder float *posptr = pos+9; float m = rot[0], n = rot[1]; for (int h=0; h<res; h++) { float tmp0, tmp1, tmp2; tmp0 = m*perp[0] + n*perp2[0]; // add the normal tmp1 = m*perp[1] + n*perp2[1]; tmp2 = m*perp[2] + n*perp2[2]; posptr[0] = tmp0; // add the normal posptr[1] = tmp1; posptr[2] = tmp2; posptr[3] = pos2[0] + rad * tmp0; // start posptr[4] = pos2[1] + rad * tmp1; posptr[5] = pos2[2] + rad * tmp2; posptr[6] = posptr[3] + lenaxis[0]; // and end of the edge posptr[7] = posptr[4] + lenaxis[1]; posptr[8] = posptr[5] + lenaxis[2]; posptr += 9; // use angle addition formulae: // cos(A+B) = cos A cos B - sin A sin B // sin(A+B) = cos A sin B + sin A cos B float mtmp = rot[0]*m - rot[1]*n; float ntmp = rot[0]*n + rot[1]*m; m = mtmp; n = ntmp; } }
float hill_reilly_ring_pucker(SmallRing &ring, float *framepos) { int N = ring.num(); // the number of atoms in the current ring #if 0 // return the default color if this isn't a 5 or 6 ring atom if (N != 5 && N != 6) return 0.0; //MK added if (N==6) { //MK do Hill-Reilly for 6-membered rings int NP = N-3; // number of puckering parameters float *X = new float[N*3]; // atom co-ordinates float *r = new float[N*3]; // bond vectors float *a = new float[NP*3]; // puckering axes float *q = new float[NP*3]; // normalized puckering vectors float *n = new float[3]; // normal to reference plane float *p = new float[3]; // a flap normal float *theta = new float[NP]; // puckering parameters float pucker_sum; float max_pucker_sum; float *atompos; int curatomid, i, j, k, l; // load ring co-ordinates for (i=0; i<N; i++) { curatomid = ring[i]; atompos = framepos + 3*curatomid; X[3*i] = atompos[0]; X[3*i+1] = atompos[1]; X[3*i+2] = atompos[2]; } // calculate bond vectors for (i=0; i<N; i++) { j = (i+1) % N; vec_sub(r+3*i,X+3*j,X+3*i); } // calculate puckering axes, flap normals and puckering vectors for (i=0; i<NP; i++) { k = (2*(i+1)) % N; j = (2*i) % N; l = (2*i+1) % N; vec_sub(a+3*i,X+3*k,X+3*j); cross_prod(p,r+3*j,r+3*l); cross_prod(q+3*i,a+3*i,p); vec_normalize(q+3*i); } // reference normal cross_prod(n,a+3*0,a+3*1); vec_normalize(n); // calculate the puckering parameters pucker_sum = 0.0; for (i=0; i<NP; i++) { theta[i] = (float(VMD_PI)/2.0f) - acosf(dot_prod(q+3*i, n)); pucker_sum += theta[i]; } // 0.6154 radians (35.26 degrees) has significance for perfect tetrahedral bond geometry (see Hill paper) max_pucker_sum = NP * 0.6154f; float pucker_scaled = pucker_sum/max_pucker_sum; pucker_sum = fabsf((pucker_scaled < 1.0f) ? pucker_scaled : 1.0f); pucker_sum = (pucker_sum < 1.0f) ? pucker_sum : 1.0f; delete [] X; delete [] r; delete [] a; delete [] q; delete [] n; delete [] p; delete [] theta; return pucker_sum; } //end MK if N==6 else { //N==5 #endif float *xring = new float[N]; float *yring = new float[N]; float *zring = new float[N]; float *displ = new float[N]; float *q = new float[N]; float *phi = new float[N]; float Q; int m; float *atompos; int curatomid; for (int i=0; i<N; i++) { curatomid = ring[i]; atompos = framepos + 3*curatomid; // pointer arithmetic is evil :) xring[i] = atompos[0]; yring[i] = atompos[1]; zring[i] = atompos[2]; } atom_displ_from_mean_plane(xring, yring, zring, displ, N); delete [] xring; delete [] yring; delete [] zring; if (cremer_pople_params(N, displ, q, phi, m, Q)) { // Q is the puckering amplitude - i.e. the intensity of the pucker. Q = (Q < 2.0f) ? Q : 2.0f; //truncate amplitude at 2 delete [] displ; delete [] q; delete [] phi; return Q; } else { delete [] displ; delete [] q; delete [] phi; return 0.0; } #if 0 } #endif }
/**************************************************************************** * * Procedure calc_reciprocal_lattice * * Arguments: cell: pointer to cell_type * * Returns: none * * Action: * Uses the direct lattice vectors in 'cell to calculate the * corresponding reciprocal lattice. * * The relationships here are, of course: * b0 = (a1 x a2) / V * b1 = (a2 x a0) / V * b2 = (a0 x a1) / V * where V = a0 . (a1 x a2) is the cell volume, a[0..2] is the direct latticce * and b[0..2] is the reciprocal lattice * *****************************************************************************/ void calc_reciprocal_lattice(cell_type *cell) { int i,j; point_type tvects[3],rvects[3]; point_type tempvect; real V; /* for molecules we shouldn't even be here */ if( cell->dim < 1 ) return; /* generate a copy of the direct lattice */ for(i=0;i<cell->dim;i++){ tvects[i].x = cell->atoms[cell->tvects[i].end].loc.x - cell->atoms[cell->tvects[i].begin].loc.x; tvects[i].y = cell->atoms[cell->tvects[i].end].loc.y - cell->atoms[cell->tvects[i].begin].loc.y; tvects[i].z = cell->atoms[cell->tvects[i].end].loc.z - cell->atoms[cell->tvects[i].begin].loc.z; } /* for one dimensional systems, there is nothing to do */ if(cell->dim == 1 ){ V = sqrt(dot_prod(&tvects[0],&tvects[0])); cell->recip_vects[0].x = tvects[0].x / V; cell->recip_vects[0].y = tvects[0].y / V; cell->recip_vects[0].z = tvects[0].z / V; return; } /********* for two dimensional systems, this is easiest if we generate a bogus third direct vector which is normalized and perpendicular to both a0 and a1: a2 = a0 x a1 / |a0 x a1| ***********/ if( cell->dim == 2 ){ cross_prod(&tvects[0],&tvects[1],&tempvect); normalize_vector(&tempvect,&tvects[2]); } /* calculate the cell volume */ cross_prod(&tvects[1],&tvects[2],&tempvect); V = dot_prod(&tvects[0],&tempvect); /* now generate the reciprocal lattice vectors */ cross_prod(&tvects[1],&tvects[2],&rvects[0]); scale_vector(&rvects[0],1.0/V); cross_prod(&tvects[2],&tvects[0],&rvects[1]); scale_vector(&rvects[1],1.0/V); if( cell->dim == 3 ){ cross_prod(&tvects[0],&tvects[1],&rvects[2]); scale_vector(&rvects[2],1.0/V); } for(i=0;i<cell->dim;i++){ cell->recip_vects[i].x = rvects[i].x; cell->recip_vects[i].y = rvects[i].y; cell->recip_vects[i].z = rvects[i].z; } #ifdef DEBUG_SYMM printf("Reciprocal Lattice:\n"); for(i=0;i<cell->dim;i++){ printf("b[%d] = (%lf %lf %lf)\n",i,rvects[i].x,rvects[i].y, rvects[i].z); } /* check orthonormality */ for(i=0;i<cell->dim;i++){ for(j=0;j<cell->dim;j++){ V = dot_prod(&tvects[i],&rvects[j]); printf("a[%d] . b[%d] = %lf\n",i,j,V); } } #endif }