1 /* Copyright (C) 2005-2007  The Chemistry Development Kit (CDK) project
2  *
3  * Contact: cdk-devel@lists.sourceforge.net
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package org.openscience.cdk.tools;
21 
22 import java.io.BufferedWriter;
23 import java.io.FileWriter;
24 import java.io.IOException;
25 
26 import javax.vecmath.Point3d;
27 
28 /**
29  * Generates a grid of points in 3D space within given boundaries.
30  *
31  * @author cho
32  * @cdk.githash
33  * @cdk.created 2005-09-30
34  */
35 public class GridGenerator {
36 
37     double       latticeConstant = 0.5;
38     double       extendGrid      = 2;
39     double[][][] grid            = null;
40     double[]     gridArray       = null;
41     double       maxx            = 0;
42     double       maxy            = 0;
43     double       maxz            = 0;
44     double       minx            = 0;
45     double       miny            = 0;
46     double       minz            = 0;
47     int[]        dim             = {0, 0, 0};
48 
GridGenerator()49     public GridGenerator() {}
50 
GridGenerator(double min, double max)51     public GridGenerator(double min, double max) {
52         setDimension(min, max);
53         generateGrid();
54     }
55 
56     /**
57      * @param initialValue used as initial value for the grid points
58      */
GridGenerator(double min, double max, double initialValue)59     public GridGenerator(double min, double max, double initialValue) {
60         setDimension(min, max);
61         generateGrid();
62         initializeGrid(initialValue);
63     }
64 
GridGenerator(double[] minMax, double initialValue, boolean cubicGridFlag)65     public GridGenerator(double[] minMax, double initialValue, boolean cubicGridFlag) {
66         setDimension(minMax, cubicGridFlag);
67         generateGrid();
68         initializeGrid(initialValue);
69     }
70 
71     /**
72      * Method sets the maximal 3d dimensions to given min and max values.
73      */
setDimension(double min, double max)74     public void setDimension(double min, double max) {
75         this.minx = min;
76         this.maxx = max;
77         this.miny = min;
78         this.maxy = max;
79         this.minz = min;
80         this.maxz = max;
81     }
82 
83     /**
84      * Method sets the maximal 3d dimensions to given min and max values.
85      */
setDimension(double[] minMax, boolean cubicGridFlag)86     public void setDimension(double[] minMax, boolean cubicGridFlag) {
87         if (cubicGridFlag) {
88             double min = minMax[0];
89             double max = minMax[0];
90             for (int i = 0; i < minMax.length; i++) {
91                 if (minMax[i] < min) {
92                     min = minMax[i];
93                 } else if (minMax[i] > max) {
94                     max = minMax[i];
95                 }
96             }
97             setDimension(min, max);
98         } else {
99             this.minx = minMax[0];
100             this.maxx = minMax[1];
101             this.miny = minMax[2];
102             this.maxy = minMax[3];
103             this.minz = minMax[4];
104             this.maxz = minMax[5];
105         }
106     }
107 
108     /**
109      * Method sets the maximal 3d dimensions to given min and max values.
110      */
setDimension(double minx, double maxx, double miny, double maxy, double minz, double maxz)111     public void setDimension(double minx, double maxx, double miny, double maxy, double minz, double maxz) {
112         this.minx = minx;
113         this.maxx = maxx;
114         this.miny = miny;
115         this.maxy = maxy;
116         this.minz = minz;
117         this.maxz = maxz;
118     }
119 
120     /**
121      * Main method creates a grid between given boundaries (dimensions).
122      * The grid my be extended over the given boundaries with the
123      * variable extendGrid.
124      */
generateGrid()125     public void generateGrid() {
126         minx = minx - extendGrid;
127         maxx = maxx + extendGrid;
128         miny = miny - extendGrid;
129         maxy = maxy + extendGrid;
130         minz = minz - extendGrid;
131         maxz = maxz + extendGrid;
132 
133         dim[0] = (int) Math.round(Math.abs(maxx - minx) / latticeConstant);
134         dim[1] = (int) Math.round(Math.abs(maxy - miny) / latticeConstant);
135         dim[2] = (int) Math.round(Math.abs(maxz - minz) / latticeConstant);
136 
137         grid = new double[dim[0] + 1][dim[1] + 1][dim[2] + 1];
138     }
139 
140     /**
141      * Method initialise the given grid points with a value.
142      */
initializeGrid(double value)143     public void initializeGrid(double value) {
144         for (int i = 0; i < grid.length; i++) {
145             for (int j = 0; j < grid[0].length; j++) {
146                 for (int k = 0; k < grid[0][0].length; k++) {
147                     grid[k][j][i] = value;
148                 }
149             }
150         }
151     }
152 
153     /**
154      * Method initialise the given grid points with a value.
155      */
initializeGrid(double grid[][][], double value)156     public double[][][] initializeGrid(double grid[][][], double value) {
157         for (int i = 0; i < grid.length; i++) {
158             for (int j = 0; j < grid[0].length; j++) {
159                 for (int k = 0; k < grid[0][0].length; k++) {
160                     grid[k][j][i] = value;
161                 }
162             }
163         }
164         return grid;
165     }
166 
167     /**
168      * Method transforms the grid to an array.
169      */
gridToGridArray(double[][][] grid)170     public double[] gridToGridArray(double[][][] grid) {
171         if (grid == null) {
172             grid = this.grid;
173         }
174         gridArray = new double[dim[0] * dim[1] * dim[2] + 3];
175         int dimCounter = 0;
176         for (int z = 0; z < grid[0][0].length; z++) {
177             for (int y = 0; y < grid[0].length; y++) {
178                 for (int x = 0; x < grid.length; x++) {
179                     gridArray[dimCounter] = grid[x][y][z];
180                     dimCounter++;
181                 }
182             }
183         }
184         return gridArray;
185     }
186 
187     /**
188      * Method calculates coordinates from a given grid point.
189      */
getCoordinatesFromGridPoint(Point3d gridPoint)190     public Point3d getCoordinatesFromGridPoint(Point3d gridPoint) {
191         double dx = minx + latticeConstant * gridPoint.x;
192         double dy = miny + latticeConstant * gridPoint.y;
193         double dz = minz + latticeConstant * gridPoint.z;
194         return new Point3d(dx, dy, dz);
195     }
196 
197     /**
198      * Method calculates coordinates from a given grid array position.
199      */
getCoordinatesFromGridPoint(int gridPoint)200     public Point3d getCoordinatesFromGridPoint(int gridPoint) {
201         int dimCounter = 0;
202         Point3d point = new Point3d(0, 0, 0);
203         for (int z = 0; z < grid[0][0].length; z++) {
204             for (int y = 0; y < grid[0].length; y++) {
205                 for (int x = 0; x < grid.length; x++) {
206                     if (dimCounter == gridPoint) {
207                         point.x = minx + latticeConstant * x;
208                         point.y = miny + latticeConstant * y;
209                         point.z = minz + latticeConstant * z;
210                         return point;
211                     }
212                     dimCounter++;
213                 }
214             }
215         }
216         return point;
217     }
218 
219     /**
220      * Method calculates the nearest grid point from given coordinates.
221      */
getGridPointFrom3dCoordinates(Point3d coord)222     public Point3d getGridPointFrom3dCoordinates(Point3d coord) throws Exception {
223         Point3d gridPoint = new Point3d();
224 
225         if (coord.x >= minx & coord.x <= maxx) {
226             gridPoint.x = (int) Math.round(Math.abs(minx - coord.x) / latticeConstant);
227         } else {
228             throw new Exception("CDKGridError: Given coordinates are not in grid");
229         }
230         if (coord.y >= miny & coord.y <= maxy) {
231             gridPoint.y = (int) Math.round(Math.abs(miny - coord.y) / latticeConstant);
232         } else {
233             throw new Exception("CDKGridError: Given coordinates are not in grid");
234         }
235         if (coord.z >= minz & coord.z <= maxz) {
236             gridPoint.z = (int) Math.round(Math.abs(minz - coord.z) / latticeConstant);
237         } else {
238             throw new Exception("CDKGridError: Given coordinates are not in grid");
239         }
240 
241         return gridPoint;
242     }
243 
244     /**
245      * Method transforms the grid into pmesh format.
246      */
writeGridInPmeshFormat(String outPutFileName)247     public void writeGridInPmeshFormat(String outPutFileName) throws IOException {
248         BufferedWriter writer = new BufferedWriter(new FileWriter(outPutFileName + ".pmesh"));
249         int numberOfGridPoints = grid.length * grid[0].length * grid[0][0].length;
250         writer.write(numberOfGridPoints + "\n");
251         for (int z = 0; z < grid[0][0].length; z++) {
252             for (int y = 0; y < grid[0].length; y++) {
253                 for (int x = 0; x < grid.length; x++) {
254                     Point3d coords = getCoordinatesFromGridPoint(new Point3d(x, y, z));
255                     writer.write(coords.x + "\t" + coords.y + "\t" + coords.z + "\n");
256                 }
257             }
258         }
259         writer.close();
260     }
261 
262     /**
263      * Method transforms the grid into pmesh format. Only grid points
264      * with specific value defined with cutoff are considered.
265      * <pre>{@code
266      * cutoff <0, the values considered must be <=cutoff
267      * cutoff >0, the values considered must be >=cutoff
268      * }</pre>
269      */
writeGridInPmeshFormat(String outPutFileName, double cutOff)270     public void writeGridInPmeshFormat(String outPutFileName, double cutOff) throws IOException {
271         BufferedWriter writer = new BufferedWriter(new FileWriter(outPutFileName + ".pmesh"));
272         boolean negative = false;
273         if (cutOff < 0) {
274             negative = true;
275         } else {
276             negative = false;
277         }
278         int numberOfGridPoints = 0;
279         for (int z = 0; z < grid[0][0].length; z++) {
280             for (int y = 0; y < grid[0].length; y++) {
281                 for (int x = 0; x < grid.length; x++) {
282                     if (negative) {
283                         if (grid[x][y][z] <= cutOff) {
284                             numberOfGridPoints++;
285                         }
286                     } else {
287                         if (grid[x][y][z] >= cutOff) {
288                             numberOfGridPoints++;
289                         }
290                     }
291                 }
292             }
293         }
294         writer.write(numberOfGridPoints + "\n");
295         for (int z = 0; z < grid[0][0].length; z++) {
296             for (int y = 0; y < grid[0].length; y++) {
297                 for (int x = 0; x < grid.length; x++) {
298                     Point3d coords = getCoordinatesFromGridPoint(new Point3d(x, y, z));
299                     if (negative) {
300                         if (grid[x][y][z] <= cutOff) {
301                             writer.write(coords.x + "\t" + coords.y + "\t" + coords.z + "\n");
302                         }
303                     } else {
304                         if (grid[x][y][z] >= cutOff) {
305                             writer.write(coords.x + "\t" + coords.y + "\t" + coords.z + "\n");
306                         }
307                     }
308                 }
309             }
310         }
311         writer.close();
312     }
313 
314     @Override
toString()315     public String toString() {
316         return "Dim:" + dim + " SizeX:" + grid.length + " SizeY:" + grid[0].length + " SizeZ:" + grid[0][0].length
317                 + "\nminx:" + minx + " maxx:" + maxx + "\nminy:" + miny + " maxy:" + maxy + "\nminz:" + minz + " maxz:"
318                 + maxz;
319     }
320 
321     /**
322      * @return Returns the dim.
323      */
getDim()324     public int[] getDim() {
325         return dim;
326     }
327 
328     /**
329      * @param dim The dim to set.
330      */
setDim(int[] dim)331     public void setDim(int[] dim) {
332         this.dim = dim;
333     }
334 
335     /**
336      * @return Returns the extendGrid.
337      */
getExtendGrid()338     public double getExtendGrid() {
339         return extendGrid;
340     }
341 
342     /**
343      * @param extendGrid The extendGrid to set.
344      */
setExtendGrid(double extendGrid)345     public void setExtendGrid(double extendGrid) {
346         this.extendGrid = extendGrid;
347     }
348 
349     /**
350      * @return Returns the grid.
351      */
getGrid()352     public double[][][] getGrid() {
353         return grid;
354     }
355 
356     /**
357      * @param grid The grid to set.
358      */
setGrid(double[][][] grid)359     public void setGrid(double[][][] grid) {
360         this.grid = grid;
361     }
362 
363     /**
364      * @return Returns the latticeConstant.
365      */
getLatticeConstant()366     public double getLatticeConstant() {
367         return latticeConstant;
368     }
369 
370     /**
371      * @param latticeConstant The latticeConstant to set.
372      */
setLatticeConstant(double latticeConstant)373     public void setLatticeConstant(double latticeConstant) {
374         this.latticeConstant = latticeConstant;
375     }
376 
377     /**
378      * @return Returns the gridArray.
379      */
getGridArray()380     public double[] getGridArray() {
381         return gridArray;
382     }
383 
384     /**
385      * @return Returns the maxx.
386      */
getMaxx()387     public double getMaxx() {
388         return maxx;
389     }
390 
391     /**
392      * @return Returns the maxy.
393      */
getMaxy()394     public double getMaxy() {
395         return maxy;
396     }
397 
398     /**
399      * @return Returns the maxz.
400      */
getMaxz()401     public double getMaxz() {
402         return maxz;
403     }
404 
405     /**
406      * @return Returns the minx.
407      */
getMinx()408     public double getMinx() {
409         return minx;
410     }
411 
412     /**
413      * @return Returns the miny.
414      */
getMiny()415     public double getMiny() {
416         return miny;
417     }
418 
419     /**
420      * @return Returns the minz.
421      */
getMinz()422     public double getMinz() {
423         return minz;
424     }
425 
426 }
427