/*
* Copyright (C) 2004-2007 The Chemistry Development Kit (CDK) project
*
* Contact: cdk-devel@lists.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.openscience.cdk.geometry.surface;
import org.openscience.cdk.interfaces.IAtom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Creates a list of atoms neighboring each atom in the molecule.
*
* <p>The routine is a simplified version of the neighbor list described
* in {@cdk.cite EIS95} and is based on the implementation by Peter McCluskey.
* Due to the fact that it divides the cube into a fixed number of sub cubes,
* some accuracy may be lost.
*
* @author Rajarshi Guha
* @cdk.created 2005-05-09
* @cdk.module extra
* @cdk.githash
*/
public class NeighborList {
HashMap<String,List> boxes;
double boxSize;
IAtom[] atoms;
public NeighborList(IAtom[] atoms, double radius) {
this.atoms = atoms;
this.boxes = new HashMap<String,List>();
this.boxSize = 2 * radius;
for (int i = 0; i < atoms.length; i++) {
String key = getKeyString(atoms[i]);
if (this.boxes.containsKey(key)) {
List arl = this.boxes.get(key);
arl.add(i);
this.boxes.put( key, arl );
} else {
this.boxes.put( key, new ArrayList() );
}
}
}
private String getKeyString(IAtom atom) {
double x = atom.getPoint3d().x;
double y = atom.getPoint3d().y;
double z = atom.getPoint3d().z;
int k1,k2,k3;
k1 = (int)(Math.floor(x/ boxSize));
k2 = (int)(Math.floor(y/ boxSize));
k3 = (int)(Math.floor(z/ boxSize));
String key =
Integer.toString(k1) + " " +
Integer.toString(k2) + " " +
Integer.toString(k3) + " " ;
return(key);
}
private int[] getKeyArray(IAtom atom) {
double x = atom.getPoint3d().x;
double y = atom.getPoint3d().y;
double z = atom.getPoint3d().z;
int k1,k2,k3;
k1 = (int)(Math.floor(x/ boxSize));
k2 = (int)(Math.floor(y/ boxSize));
k3 = (int)(Math.floor(z/ boxSize));
int[] ret = { k1, k2, k3 };
return(ret);
}
public int getNumberOfNeighbors(int i) {
return getNeighbors(i).length;
}
public int[] getNeighbors(int ii) {
double maxDist2 = this.boxSize *this.boxSize;
IAtom ai = this.atoms[ii];
int[] key = getKeyArray(ai);
ArrayList nlist = new ArrayList();
int[] bval = {-1,0,1};
for (int i = 0; i < bval.length; i++) {
int x = bval[i];
for (int j = 0; j < bval.length; j++) {
int y = bval[j];
for (int k = 0; k < bval.length; k++) {
int z = bval[k];
String keyj =
Integer.toString(key[0]+x) + " " +
Integer.toString(key[1]+y) + " " +
Integer.toString(key[2]+z) + " " ;
if (boxes.containsKey(keyj)) {
ArrayList nbrs = (ArrayList)boxes.get(keyj);
for (int l = 0; l < nbrs.size(); l++) {
int i2 = (Integer) nbrs.get(l);
if (i2 != ii) {
IAtom aj = atoms[i2];
double x12 = aj.getPoint3d().x - ai.getPoint3d().x;
double y12 = aj.getPoint3d().y - ai.getPoint3d().y;
double z12 = aj.getPoint3d().z - ai.getPoint3d().z;
double d2 = x12*x12 + y12*y12 + z12*z12;
if (d2 < maxDist2) nlist.add(i2);
}
}
}
}
}
}
Object[] tmp = nlist.toArray();
int[] ret = new int[ tmp.length ];
for (int j = 0; j < tmp.length; j++) ret[j] = (Integer) tmp[j];
return(ret);
}
}