void get_transform_to_orthonormal_cell(const float *cell, const float *center, Matrix4 &transform) { // Orthogonalize system: // Find an orthonormal basis of the cell (in cartesian coords). // If the cell vectors from VMD/NAMD are used this should actually always // return the identity matrix due to the way the cell vectors A, B and C // are defined (i.e. A || x; B lies in the x,y-plane; A, B, C form a right // hand system). float obase[3*3]; orthonormal_basis(cell, obase); // Get orthonormal base in cartesian coordinates (it is the inverse of the // obase->cartesian transformation): float identity[3*3] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; float obase_cartcoor[3*3]; basis_change(obase, identity, obase_cartcoor, 3); // Transform 3x3 into 4x4 matrix: Matrix4 obase2cartinv; trans_from_rotate(obase_cartcoor, &obase2cartinv); // This is the matrix for the obase->cartesian transformation: Matrix4 obase2cart = obase2cartinv; obase2cart.inverse(); // Get coordinates of cell in terms of obase float m[3*3]; basis_change(cell, obase, m, 3); Matrix4 rotmat; trans_from_rotate(m, &rotmat); rotmat.inverse(); // Actually we have: // transform = translation * obase2cart * obase2cartinv * rotmat * obase2cart // `------------v------------' // = 1 transform = obase2cart; transform.multmatrix(rotmat); // pre-multiplication // Finally we need to apply the translation of the origin float origin[3]; vec_copy(origin, center); vec_scaled_add(origin, -0.5, &cell[0]); vec_scaled_add(origin, -0.5, &cell[3]); vec_scaled_add(origin, -0.5, &cell[6]); vec_negate(origin, origin); //printf("origin={%g %g %g}\n", origin[0], origin[1], origin[2]); transform.translate(origin); }
void SMat<CoeffRing>::subtractInPlace(const SMat<CoeffRing> &B) // this -= B. // assumption:the assert statements below: { assert(&B.ring() == &ring()); assert(B.numRows() == numRows()); assert(B.numColumns() == numColumns()); for (size_t c = 0; c < numColumns(); c++) { sparsevec *v = vec_copy(B.columns_[c]); vec_negate(v); vec_add_to(columns_[c], v); } }
void TachyonDisplayDevice::start_clipgroup(void) { int i; int planesenabled = 0; for (i=0; i<VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] > 0) { planesenabled++; /* count number of active clipping planes */ if (clip_mode[i] > 1) warningflags |= FILERENDERER_NOCLIP; /* emit warnings */ } } if (planesenabled > 0) { fprintf(outfile, "Start_ClipGroup\n"); fprintf(outfile, " NumPlanes %d\n", planesenabled); for (i=0; i<VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] > 0) { float tachyon_clip_center[3]; float tachyon_clip_normal[3]; float tachyon_clip_distance; inclipgroup = 1; // we're in a clipping group presently // Transform the plane center and the normal (transMat.top()).multpoint3d(clip_center[i], tachyon_clip_center); (transMat.top()).multnorm3d(clip_normal[i], tachyon_clip_normal); vec_negate(tachyon_clip_normal, tachyon_clip_normal); // Tachyon uses the distance from the origin to the plane for its // representation, instead of the plane center tachyon_clip_distance = dot_prod(tachyon_clip_normal, tachyon_clip_center); fprintf(outfile, "%g %g %g %g\n", tachyon_clip_normal[0], tachyon_clip_normal[1], -tachyon_clip_normal[2], tachyon_clip_distance); } } fprintf(outfile, "\n"); } else { inclipgroup = 0; // Not currently in a clipping group } }
vec<N,S> operator-(vec<N,S> const& v) { return vec_negate(v); }
static void compute_grad_point(struct efp *efp, size_t frag_idx, size_t pt_idx) { const struct frag *fr_i = efp->frags + frag_idx; const struct polarizable_pt *pt_i = fr_i->polarizable_pts + pt_idx; size_t idx_i = fr_i->polarizable_offset + pt_idx; vec_t dipole_i = { 0.5 * (efp->indip[idx_i].x + efp->indipconj[idx_i].x), 0.5 * (efp->indip[idx_i].y + efp->indipconj[idx_i].y), 0.5 * (efp->indip[idx_i].z + efp->indipconj[idx_i].z) }; for (size_t j = 0; j < efp->n_frag; j++) { if (j == frag_idx || efp_skip_frag_pair(efp, frag_idx, j)) continue; struct frag *fr_j = efp->frags + j; struct swf swf = efp_make_swf(efp, fr_i, fr_j); /* energy without switching applied */ double energy = 0.0; /* induced dipole - nuclei */ for (size_t k = 0; k < fr_j->n_atoms; k++) { struct efp_atom *at_j = fr_j->atoms + k; vec_t dr = { at_j->x - pt_i->x - swf.cell.x, at_j->y - pt_i->y - swf.cell.y, at_j->z - pt_i->z - swf.cell.z }; double p1 = 1.0, p2 = 0.0; if (efp->opts.pol_damp == EFP_POL_DAMP_TT) { double r = vec_len(&dr); p1 = efp_get_pol_damp_tt(r, fr_i->pol_damp, fr_j->pol_damp); p2 = efp_get_pol_damp_tt_grad(r, fr_i->pol_damp, fr_j->pol_damp); } vec_t force, add_i, add_j; double e = -efp_charge_dipole_energy(at_j->znuc, &dipole_i, &dr); efp_charge_dipole_grad(at_j->znuc, &dipole_i, &dr, &force, &add_j, &add_i); vec_negate(&force); vec_scale(&force, p1); vec_scale(&add_i, p1); vec_scale(&add_j, p1); force.x += p2 * e * dr.x; force.y += p2 * e * dr.y; force.z += p2 * e * dr.z; vec_scale(&force, swf.swf); vec_scale(&add_i, swf.swf); vec_scale(&add_j, swf.swf); efp_add_force(efp->grad + frag_idx, CVEC(fr_i->x), CVEC(pt_i->x), &force, &add_i); efp_sub_force(efp->grad + j, CVEC(fr_j->x), CVEC(at_j->x), &force, &add_j); efp_add_stress(&swf.dr, &force, &efp->stress); energy += p1 * e; } /* induced dipole - multipoles */ for (size_t k = 0; k < fr_j->n_multipole_pts; k++) { struct multipole_pt *pt_j = fr_j->multipole_pts + k; vec_t dr = { pt_j->x - pt_i->x - swf.cell.x, pt_j->y - pt_i->y - swf.cell.y, pt_j->z - pt_i->z - swf.cell.z }; double p1 = 1.0, p2 = 0.0; if (efp->opts.pol_damp == EFP_POL_DAMP_TT) { double r = vec_len(&dr); p1 = efp_get_pol_damp_tt(r, fr_i->pol_damp, fr_j->pol_damp); p2 = efp_get_pol_damp_tt_grad(r, fr_i->pol_damp, fr_j->pol_damp); } double e = 0.0; vec_t force_, add_i_, add_j_; vec_t force = vec_zero, add_i = vec_zero, add_j = vec_zero; /* induced dipole - charge */ e -= efp_charge_dipole_energy(pt_j->monopole, &dipole_i, &dr); efp_charge_dipole_grad(pt_j->monopole, &dipole_i, &dr, &force_, &add_j_, &add_i_); vec_negate(&force_); add_3(&force, &force_, &add_i, &add_i_, &add_j, &add_j_); /* induced dipole - dipole */ e += efp_dipole_dipole_energy(&dipole_i, &pt_j->dipole, &dr); efp_dipole_dipole_grad(&dipole_i, &pt_j->dipole, &dr, &force_, &add_i_, &add_j_); vec_negate(&add_j_); add_3(&force, &force_, &add_i, &add_i_, &add_j, &add_j_); /* induced dipole - quadrupole */ e += efp_dipole_quadrupole_energy(&dipole_i, pt_j->quadrupole, &dr); efp_dipole_quadrupole_grad(&dipole_i, pt_j->quadrupole, &dr, &force_, &add_i_, &add_j_); add_3(&force, &force_, &add_i, &add_i_, &add_j, &add_j_); /* induced dipole - octupole interactions are ignored */ vec_scale(&force, p1); vec_scale(&add_i, p1); vec_scale(&add_j, p1); force.x += p2 * e * dr.x; force.y += p2 * e * dr.y; force.z += p2 * e * dr.z; vec_scale(&force, swf.swf); vec_scale(&add_i, swf.swf); vec_scale(&add_j, swf.swf); efp_add_force(efp->grad + frag_idx, CVEC(fr_i->x), CVEC(pt_i->x), &force, &add_i); efp_sub_force(efp->grad + j, CVEC(fr_j->x), CVEC(pt_j->x), &force, &add_j); efp_add_stress(&swf.dr, &force, &efp->stress); energy += p1 * e; } /* induced dipole - induced dipoles */ for (size_t jj = 0; jj < fr_j->n_polarizable_pts; jj++) { struct polarizable_pt *pt_j = fr_j->polarizable_pts + jj; size_t idx_j = fr_j->polarizable_offset + jj; vec_t dr = { pt_j->x - pt_i->x - swf.cell.x, pt_j->y - pt_i->y - swf.cell.y, pt_j->z - pt_i->z - swf.cell.z }; vec_t half_dipole_i = { 0.5 * efp->indip[idx_i].x, 0.5 * efp->indip[idx_i].y, 0.5 * efp->indip[idx_i].z }; double p1 = 1.0, p2 = 0.0; if (efp->opts.pol_damp == EFP_POL_DAMP_TT) { double r = vec_len(&dr); p1 = efp_get_pol_damp_tt(r, fr_i->pol_damp, fr_j->pol_damp); p2 = efp_get_pol_damp_tt_grad(r, fr_i->pol_damp, fr_j->pol_damp); } vec_t force, add_i, add_j; double e = efp_dipole_dipole_energy(&half_dipole_i, &efp->indipconj[idx_j], &dr); efp_dipole_dipole_grad(&half_dipole_i, &efp->indipconj[idx_j], &dr, &force, &add_i, &add_j); vec_negate(&add_j); vec_scale(&force, p1); vec_scale(&add_i, p1); vec_scale(&add_j, p1); force.x += p2 * e * dr.x; force.y += p2 * e * dr.y; force.z += p2 * e * dr.z; vec_scale(&force, swf.swf); vec_scale(&add_i, swf.swf); vec_scale(&add_j, swf.swf); efp_add_force(efp->grad + frag_idx, CVEC(fr_i->x), CVEC(pt_i->x), &force, &add_i); efp_sub_force(efp->grad + j, CVEC(fr_j->x), CVEC(pt_j->x), &force, &add_j); efp_add_stress(&swf.dr, &force, &efp->stress); energy += p1 * e; } vec_t force = { swf.dswf.x * energy, swf.dswf.y * energy, swf.dswf.z * energy }; six_atomic_add_xyz(efp->grad + frag_idx, &force); six_atomic_sub_xyz(efp->grad + j, &force); efp_add_stress(&swf.dr, &force, &efp->stress); } /* induced dipole - ab initio nuclei */ if (efp->opts.terms & EFP_TERM_AI_POL) { for (size_t j = 0; j < efp->n_ptc; j++) { vec_t dr = vec_sub(efp->ptc_xyz + j, CVEC(pt_i->x)); vec_t force, add_i, add_j; efp_charge_dipole_grad(efp->ptc[j], &dipole_i, &dr, &force, &add_j, &add_i); vec_negate(&add_i); vec_atomic_add(efp->ptc_grad + j, &force); efp_sub_force(efp->grad + frag_idx, CVEC(fr_i->x), CVEC(pt_i->x), &force, &add_i); } } }
int measure_pbc_neighbors(MoleculeList *mlist, AtomSel *sel, int molid, int frame, const Matrix4 *alignment, const float *center, const float *cutoff, const float *box, ResizeArray<float> *extcoord_array, ResizeArray<int> *indexmap_array) { int orig_ts, max_ts; if (!box && !cutoff[0] && !cutoff[1] && !cutoff[2]) return MEASURE_NOERR; Molecule *mol = mlist->mol_from_id(molid); if( !mol ) return MEASURE_ERR_NOMOLECULE; // get current frame number and make sure there are frames if((orig_ts = mol->frame()) < 0) return MEASURE_ERR_NOFRAMES; // get the max frame number and determine current frame max_ts = mol->numframes()-1; if (frame==-2) frame = orig_ts; else if (frame>max_ts || frame==-1) frame = max_ts; Timestep *ts = mol->get_frame(frame); if (!ts) return MEASURE_ERR_NOMOLECULE; // Get the displacement vectors (in form of translation matrices) Matrix4 Tpbc[3][2]; ts->get_transforms(Tpbc[0][1], Tpbc[1][1], Tpbc[2][1]); // Assign the negative cell translation vectors Tpbc[0][0] = Tpbc[0][1]; Tpbc[1][0] = Tpbc[1][1]; Tpbc[2][0] = Tpbc[2][1]; Tpbc[0][0].inverse(); Tpbc[1][0].inverse(); Tpbc[2][0].inverse(); // Construct the cell spanning vectors float cell[9]; cell[0] = Tpbc[0][1].mat[12]; cell[1] = Tpbc[0][1].mat[13]; cell[2] = Tpbc[0][1].mat[14]; cell[3] = Tpbc[1][1].mat[12]; cell[4] = Tpbc[1][1].mat[13]; cell[5] = Tpbc[1][1].mat[14]; cell[6] = Tpbc[2][1].mat[12]; cell[7] = Tpbc[2][1].mat[13]; cell[8] = Tpbc[2][1].mat[14]; float len[3]; len[0] = sqrtf(dot_prod(&cell[0], &cell[0])); len[1] = sqrtf(dot_prod(&cell[3], &cell[3])); len[2] = sqrtf(dot_prod(&cell[6], &cell[6])); //printf("len={%.3f %.3f %.3f}\n", len[0], len[1], len[2]); int i; float minlen = len[0]; if (len[1] && len[1]<minlen) minlen = len[1]; if (len[2] && len[2]<minlen) minlen = len[2]; minlen--; // The algorithm works only for atoms in adjacent neighbor cells. if (!box && (cutoff[0]>=len[0] || cutoff[1]>=len[1] || cutoff[2]>=len[2])) { return MEASURE_ERR_BADCUTOFF; } bool bigrim = 1; float corecell[9]; float diag[3]; float origin[3]; memset(origin, 0, 3*sizeof(float)); Matrix4 M_norm; if (box) { // Get the matrix M_norm that transforms all atoms inside the // unit cell into the normalized unitcell spanned by // {1/len[0] 0 0} {0 1/len[1] 0} {0 0 1/len[2]}. bigrim = 1; float vtmp[3]; vec_add(vtmp, &cell[0], &cell[3]); vec_add(diag, &cell[6], vtmp); //printf("diag={%.3f %.3f %.3f}\n", diag[0], diag[1], diag[2]); // Finally we need to apply the translation of the cell origin vec_copy(origin, center); vec_scaled_add(origin, -0.5, &cell[0]); vec_scaled_add(origin, -0.5, &cell[3]); vec_scaled_add(origin, -0.5, &cell[6]); vec_negate(origin, origin); //printf("origin={%.3f %.3f %.3f}\n", origin[0], origin[1], origin[2]); } else if (2.0f*cutoff[0]<minlen && 2.0f*cutoff[1]<minlen && 2.0f*cutoff[2]<minlen) { // The cutoff must not be larger than half of the smallest cell dimension // otherwise we would have to use a less efficient algorithm. // Get the matrix M_norm that transforms all atoms inside the // corecell into the orthonormal unitcell spanned by {1 0 0} {0 1 0} {0 0 1}. // The corecell ist the pbc cell minus cutoffs for each dimension. vec_scale(&corecell[0], (len[0]-cutoff[0])/len[0], &cell[0]); vec_scale(&corecell[3], (len[1]-cutoff[1])/len[1], &cell[3]); vec_scale(&corecell[6], (len[2]-cutoff[2])/len[2], &cell[6]); get_transform_to_orthonormal_cell(corecell, center, M_norm); //printf("Using algorithm for small PBC environment.\n"); } else { // Get the matrix M_norm that transforms all atoms inside the // unit cell into the orthonormal unitcell spanned by {1 0 0} {0 1 0} {0 0 1}. get_transform_to_orthonormal_cell(cell, center, M_norm); bigrim = 1; //printf("Using algorithm for large PBC environment.\n"); } // In case the molecule was aligned our pbc cell is rotated and shifted. // In order to transform a point P into the orthonormal cell (P') it // first has to be unaligned (the inverse of the alignment): // P' = M_norm * (alignment^-1) * P Matrix4 alignmentinv(*alignment); alignmentinv.inverse(); Matrix4 M_coretransform(M_norm); M_coretransform.multmatrix(alignmentinv); //printf("alignment = \n"); //print_Matrix4(alignment); // Similarly if we want to transform a point P into its image P' we // first have to unalign it, then apply the PBC translation and // finally realign: // P' = alignment * Tpbc * (alignment^-1) * P // `-------------v--------------' // transform int j, u; Matrix4 Tpbc_aligned[3][2]; if (!box) { for (i=0; i<3; i++) { for (j=0; j<2; j++) { Tpbc_aligned[i][j].loadmatrix(*alignment); Tpbc_aligned[i][j].multmatrix(Tpbc[i][j]); Tpbc_aligned[i][j].multmatrix(alignmentinv); } } } Matrix4 M[3]; float *coords = ts->pos; float *coor; float orthcoor[3], wrapcoor[3]; //printf("cutoff={%.3f %.3f %.3f}\n", cutoff[0], cutoff[1], cutoff[2]); if (box) { float min_coord[3], max_coord[3]; // Increase box by cutoff vec_sub(min_coord, box, cutoff); vec_add(max_coord, box+3, cutoff); //printf("Wrapping atoms into rectangular bounding box.\n"); //printf("min_coord={%.3f %.3f %.3f}\n", min_coord[0], min_coord[1], min_coord[2]); //printf("max_coord={%.3f %.3f %.3f}\n", max_coord[0], max_coord[1], max_coord[2]); vec_add(min_coord, min_coord, origin); vec_add(max_coord, max_coord, origin); float testcoor[9]; int idx, k; // Loop over all atoms for (idx=0; idx<ts->num; idx++) { coor = coords+3*idx; // Apply the inverse alignment transformation // to the current test point. M_coretransform.multpoint3d(coor, orthcoor); // Loop over all 26 neighbor cells // x for (i=-1; i<=1; i++) { // Choose the direction of translation if (i>0) M[0].loadmatrix(Tpbc[0][1]); else if (i<0) M[0].loadmatrix(Tpbc[0][0]); else M[0].identity(); // Translate the unaligned atom M[0].multpoint3d(orthcoor, testcoor); // y for (j=-1; j<=1; j++) { // Choose the direction of translation if (j>0) M[1].loadmatrix(Tpbc[1][1]); else if (j<0) M[1].loadmatrix(Tpbc[1][0]); else M[1].identity(); // Translate the unaligned atom M[1].multpoint3d(testcoor, testcoor+3); // z for (k=-1; k<=1; k++) { if(i==0 && j==0 && k==0) continue; // Choose the direction of translation if (k>0) M[2].loadmatrix(Tpbc[2][1]); else if (k<0) M[2].loadmatrix(Tpbc[2][0]); else M[2].identity(); // Translate the unaligned atom M[2].multpoint3d(testcoor+3, testcoor+6); // Realign atom alignment->multpoint3d(testcoor+6, wrapcoor); vec_add(testcoor+6, wrapcoor, origin); if (testcoor[6]<min_coord[0] || testcoor[6]>max_coord[0]) continue; if (testcoor[7]<min_coord[1] || testcoor[7]>max_coord[1]) continue; if (testcoor[8]<min_coord[2] || testcoor[8]>max_coord[2]) continue; // Atom is inside cutoff, add it to the list for (int n=0; n<3; n++) extcoord_array->append(wrapcoor[n]); indexmap_array->append(idx); } } } } } else if (bigrim) { // This is the more general but slower algorithm. // We loop over all atoms, move each atom to all 26 neighbor cells // and check if it lies inside cutoff float min_coord[3], max_coord[3]; min_coord[0] = -cutoff[0]/len[0]; min_coord[1] = -cutoff[1]/len[1]; min_coord[2] = -cutoff[2]/len[2]; max_coord[0] = 1.0f + cutoff[0]/len[0]; max_coord[1] = 1.0f + cutoff[1]/len[1]; max_coord[2] = 1.0f + cutoff[2]/len[2]; float testcoor[3]; int idx, k; // Loop over all atoms for (idx=0; idx<ts->num; idx++) { coor = coords+3*idx; // Apply the PBC --> orthonormal unitcell transformation // to the current test point. M_coretransform.multpoint3d(coor, orthcoor); // Loop over all 26 neighbor cells // x for (i=-1; i<=1; i++) { testcoor[0] = orthcoor[0]+(float)(i); if (testcoor[0]<min_coord[0] || testcoor[0]>max_coord[0]) continue; // Choose the direction of translation if (i>0) M[0].loadmatrix(Tpbc_aligned[0][1]); else if (i<0) M[0].loadmatrix(Tpbc_aligned[0][0]); else M[0].identity(); // y for (j=-1; j<=1; j++) { testcoor[1] = orthcoor[1]+(float)(j); if (testcoor[1]<min_coord[1] || testcoor[1]>max_coord[1]) continue; // Choose the direction of translation if (j>0) M[1].loadmatrix(Tpbc_aligned[1][1]); else if (j<0) M[1].loadmatrix(Tpbc_aligned[1][0]); else M[1].identity(); // z for (k=-1; k<=1; k++) { testcoor[2] = orthcoor[2]+(float)(k); if (testcoor[2]<min_coord[2] || testcoor[2]>max_coord[2]) continue; if(i==0 && j==0 && k==0) continue; // Choose the direction of translation if (k>0) M[2].loadmatrix(Tpbc_aligned[2][1]); else if (k<0) M[2].loadmatrix(Tpbc_aligned[2][0]); else M[2].identity(); M[0].multpoint3d(coor, wrapcoor); M[1].multpoint3d(wrapcoor, wrapcoor); M[2].multpoint3d(wrapcoor, wrapcoor); // Atom is inside cutoff, add it to the list for (int n=0; n<3; n++) extcoord_array->append(wrapcoor[n]); indexmap_array->append(idx); } } } } } else { Matrix4 Mtmp; for (i=0; i < ts->num; i++) { // Apply the PBC --> orthonormal unitcell transformation // to the current test point. M_coretransform.multpoint3d(coords+3*i, orthcoor); // Determine in which cell we are. int cellindex[3]; if (orthcoor[0]<0) cellindex[0] = -1; else if (orthcoor[0]>1) cellindex[0] = 1; else cellindex[0] = 0; if (orthcoor[1]<0) cellindex[1] = -1; else if (orthcoor[1]>1) cellindex[1] = 1; else cellindex[1] = 0; if (orthcoor[2]<0) cellindex[2] = -1; else if (orthcoor[2]>1) cellindex[2] = 1; else cellindex[2] = 0; // All zero means we're inside the core --> no image. if (!cellindex[0] && !cellindex[1] && !cellindex[2]) continue; // Choose the direction of translation if (orthcoor[0]<0) M[0].loadmatrix(Tpbc_aligned[0][1]); else if (orthcoor[0]>1) M[0].loadmatrix(Tpbc_aligned[0][0]); if (orthcoor[1]<0) M[1].loadmatrix(Tpbc_aligned[1][1]); else if (orthcoor[1]>1) M[1].loadmatrix(Tpbc_aligned[1][0]); if (orthcoor[2]<0) M[2].loadmatrix(Tpbc_aligned[2][1]); else if (orthcoor[2]>1) M[2].loadmatrix(Tpbc_aligned[2][0]); // Create wrapped copies of the atom: // x, y, z planes coor = coords+3*i; for (u=0; u<3; u++) { if (cellindex[u] && cutoff[u]) { M[u].multpoint3d(coor, wrapcoor); for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]); indexmap_array->append(i); } } Mtmp = M[0]; // xy edge if (cellindex[0] && cellindex[1] && cutoff[0] && cutoff[1]) { M[0].multmatrix(M[1]); M[0].multpoint3d(coor, wrapcoor); for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]); indexmap_array->append(i); } // yz edge if (cellindex[1] && cellindex[2] && cutoff[1] && cutoff[2]) { M[1].multmatrix(M[2]); M[1].multpoint3d(coor, wrapcoor); for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]); indexmap_array->append(i); } // zx edge if (cellindex[0] && cellindex[2] && cutoff[0] && cutoff[2]) { M[2].multmatrix(Mtmp); M[2].multpoint3d(coor, wrapcoor); for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]); indexmap_array->append(i); } // xyz corner if (cellindex[0] && cellindex[1] && cellindex[2]) { M[1].multmatrix(Mtmp); M[1].multpoint3d(coor, wrapcoor); for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]); indexmap_array->append(i); } } } // endif // If a selection was provided we select extcoords // within cutoff of the original selection: if (sel) { int numext = sel->selected+indexmap_array->num(); float *extcoords = new float[3*numext]; int *indexmap = new int[numext]; int *others = new int[numext]; memset(others, 0, numext); // Use the largest given cutoff float maxcutoff = cutoff[0]; for (i=1; i<3; i++) { if (cutoff[i]>maxcutoff) maxcutoff = cutoff[i]; } // Prepare C-array of coordinates for find_within() j=0; for (i=0; i < sel->num_atoms; i++) { if (!sel->on[i]) continue; //atom is not selected extcoords[3*j] = coords[3*i]; extcoords[3*j+1] = coords[3*i+1]; extcoords[3*j+2] = coords[3*i+2]; indexmap[j] = i; others[j++] = 1; } for (i=0; i<indexmap_array->num(); i++) { extcoords[3*j] = (*extcoord_array)[3*i]; extcoords[3*j+1] = (*extcoord_array)[3*i+1]; extcoords[3*j+2] = (*extcoord_array)[3*i+2]; indexmap[j] = (*indexmap_array)[i]; others[j++] = 0; } // Initialize flags array to true, find_within() results are AND'd/OR'd in. int *flgs = new int[numext]; for (i=0; i<numext; i++) { flgs[i] = 1; } // Find coordinates from extcoords that are within cutoff of the ones // with flagged in 'others' and set the flgs accordingly: find_within(extcoords, flgs, others, numext, maxcutoff); extcoord_array->clear(); indexmap_array->clear(); for (i=sel->selected; i<numext; i++) { if (!flgs[i]) continue; extcoord_array->append(extcoords[3*i]); extcoord_array->append(extcoords[3*i+1]); extcoord_array->append(extcoords[3*i+2]); indexmap_array->append(indexmap[i]); } } return MEASURE_NOERR; }
void POV3DisplayDevice::start_clipgroup(void) { int i, num_clipplanes[3], mode; float pov_clip_center[3], pov_clip_distance[VMD_MAX_CLIP_PLANE]; float pov_clip_normal[VMD_MAX_CLIP_PLANE][3]; write_materials(); memset(num_clipplanes, 0, 3*sizeof(int)); for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] != 0) { // Count the number of clipping planes for each clip mode num_clipplanes[clip_mode[i]]++; // Translate the plane center (transMat.top()).multpoint3d(clip_center[i], pov_clip_center); // and the normal (transMat.top()).multnorm3d(clip_normal[i], pov_clip_normal[i]); vec_negate(pov_clip_normal[i], pov_clip_normal[i]); // POV-Ray uses the distance from the origin to the plane for its // representation, instead of the plane center pov_clip_distance[i] = dot_prod(pov_clip_normal[i], pov_clip_center); } } // Define the clip object for each clip mode for (mode = 1; mode < 3; mode++) { if (num_clipplanes[mode] > 0) { // This flag is used within VMD to determine if clipping information // should be written to the scene file clip_on[mode] = 1; // This flag is used within POV to determine if clipping should be done // within macros fprintf(outfile, "#declare VMD_clip_on[%d]=1;\n", mode); if (num_clipplanes[mode] == 1) { for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] == mode) { if (mode == 2) { // Textured plane for CSG clipping fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n", mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i], clip_color[i][0], clip_color[i][1], clip_color[i][2], 1 - mat_opacity); } else { // Non-textured plane for non-CSG clipping fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n", mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i]); #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND) // Non-textured plane for non-CSG clipping, but scaled for use // when emitting meshes with the scaling hack. fprintf(outfile, "#declare VMD_scaledclip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n", mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK); #endif } } } } // Declare the clipping object to be an intersection of planes else { fprintf(outfile, "#declare VMD_clip[%d] = intersection {\n", mode); for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] == mode) { if (mode == 2) { // Textured plane for CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i], clip_color[i][0], clip_color[i][1], clip_color[i][2], 1 - mat_opacity); } else { // Non-textured plane for non-CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i]); } } } fprintf(outfile, "}\n"); #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND) fprintf(outfile, "#declare VMD_scaledclip[%d] = intersection {\n", mode); for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] == mode) { if (mode == 2) { // Textured plane for CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK, clip_color[i][0], clip_color[i][1], clip_color[i][2], 1 - mat_opacity); } else { // Non-textured plane for non-CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK); } } } fprintf(outfile, "}\n"); #endif } } } }