/// <summary> /// Initialize the surface, generating the points on the accessible surface /// area of each atom as well as calculating the surface area of each atom. /// </summary> private void Init() { // invariants foreach (var atom in atoms) { if (atom.Point3D == null) { throw new ArgumentException("One or more atoms had no 3D coordinate set"); } } // get r_f and geometric center var cp = new Vector3(0, 0, 0); double maxRadius = 0; foreach (var atom in atoms) { var vdwr = PeriodicTable.GetVdwRadius(atom.Symbol).Value; if (vdwr + solventRadius > maxRadius) { maxRadius = PeriodicTable.GetVdwRadius(atom.Symbol).Value + solventRadius; } cp.X = cp.X + atom.Point3D.Value.X; cp.Y = cp.Y + atom.Point3D.Value.Y; cp.Z = cp.Z + atom.Point3D.Value.Z; } cp.X = cp.X / atoms.Length; cp.Y = cp.Y / atoms.Length; cp.Z = cp.Z / atoms.Length; // do the tesselation var tess = new Tessellate("ico", tesslevel); tess.DoTessellate(); Trace.TraceInformation($"Got tesselation, number of triangles = {tess.GetNumberOfTriangles()}"); // get neighbor list var nbrlist = new NeighborList(atoms, maxRadius + solventRadius); Trace.TraceInformation("Got neighbor list"); // loop over atoms and get surface points this.surfPoints = new List <Vector3> [atoms.Length]; this.areas = new double[atoms.Length]; this.volumes = new double[atoms.Length]; for (int i = 0; i < atoms.Length; i++) { var pointDensity = tess.GetNumberOfTriangles() * 3; var points = AtomicSurfacePoints(nbrlist, i, atoms[i], tess); TranslatePoints(i, points, pointDensity, atoms[i], cp); } Trace.TraceInformation("Obtained points, areas and volumes"); }
private Vector3[][] AtomicSurfacePoints(NeighborList nbrlist, int currAtomIdx, IAtom atom, Tessellate tess) { var totalRadius = PeriodicTable.GetVdwRadius(atom.Symbol).Value + solventRadius; var totalRadius2 = totalRadius * totalRadius; var twiceTotalRadius = 2 * totalRadius; var nlist = nbrlist.GetNeighbors(currAtomIdx); var data = Arrays.CreateJagged <double>(nlist.Length, 4); for (int i = 0; i < nlist.Length; i++) { var x12 = atoms[nlist[i]].Point3D.Value.X - atom.Point3D.Value.X; var y12 = atoms[nlist[i]].Point3D.Value.Y - atom.Point3D.Value.Y; var z12 = atoms[nlist[i]].Point3D.Value.Z - atom.Point3D.Value.Z; var d2 = x12 * x12 + y12 * y12 + z12 * z12; var tmp = PeriodicTable.GetVdwRadius(atoms[nlist[i]].Symbol).Value + solventRadius; tmp = tmp * tmp; var thresh = (d2 + totalRadius2 - tmp) / twiceTotalRadius; data[i][0] = x12; data[i][1] = y12; data[i][2] = z12; data[i][3] = thresh; } var tessPoints = tess.GetTessAsPoint3ds(); var points = new List <Vector3[]>(); foreach (var pt in tessPoints) { bool buried = false; foreach (var datum in data) { if (datum[0] * pt.X + datum[1] * pt.Y + datum[2] * pt.Z > datum[3]) { buried = true; break; } } if (!buried) { var tmp = new Vector3[2]; tmp[0] = new Vector3( totalRadius * pt.X + atom.Point3D.Value.X, totalRadius * pt.Y + atom.Point3D.Value.Y, totalRadius * pt.Z + atom.Point3D.Value.Z); tmp[1] = pt; points.Add(tmp); } } // the first column contains the transformed points // and the second column contains the points from the // original unit tesselation var ret = Arrays.CreateJagged <Vector3>(points.Count, 2); for (int i = 0; i < points.Count; i++) { var tmp = points[i]; ret[i][0] = tmp[0]; ret[i][1] = tmp[1]; } return(ret); }