├── interp ├── docs ├── DEM_Generation_SW_Design.pdf └── Out of Core implementation.doc ├── Makefile ├── INSTALL ├── RELEASE_NOTES ├── LICENSE ├── GridPoint.h ├── Global.h ├── GridFile.h ├── CoreInterp.h ├── GridMap.h ├── InCoreInterp.h ├── README.md ├── Interpolation.h ├── GridMap.cpp ├── OutCoreInterp.h ├── GridFile.cpp ├── main.cpp ├── Interpolation.cpp ├── InCoreInterp.cpp └── OutCoreInterp.cpp /interp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTopography/points2grid/main/interp -------------------------------------------------------------------------------- /docs/DEM_Generation_SW_Design.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTopography/points2grid/main/docs/DEM_Generation_SW_Design.pdf -------------------------------------------------------------------------------- /docs/Out of Core implementation.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTopography/points2grid/main/docs/Out of Core implementation.doc -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #uncomment MWIDTH to enable 64-bit compilation 2 | MWIDTH=-m64 3 | #uncomment LARGE_FILE_SUPPORT to enable support for files larger than 2GB on 32-bit systems 4 | LARGE_FILE_SUPPORT=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_USE_LARGEFILE64 5 | 6 | 7 | #uncomment for grid alignment with origin support 8 | DFLAGS +=-DALIGN_ORIGIN 9 | 10 | DFLAGS +=-DHARD_LIMIT="500000000" 11 | 12 | CC=g++ 13 | 14 | CFLAGS=-O3 -DNDEBUG $(MWIDTH) -Wall -g $(LARGE_FILE_SUPPORT) 15 | 16 | INC=-I/usr/local/include/curl -I/usr/local/include/liblas 17 | LIB=-L/usr/local/lib/curl -L/usr/local/lib -llas -lm -lcurl 18 | 19 | OBJS=main.o Interpolation.o InCoreInterp.o OutCoreInterp.o GridMap.o GridFile.o 20 | 21 | #all: interp ctags 22 | all: interp 23 | 24 | interp: $(OBJS) 25 | $(CC) $(CFLAGS) $(DFLAGS) $(LIB) $(INC) -o $@ $(OBJS) 26 | 27 | .cpp.o: 28 | $(CC) $(CFLAGS) $(DFLAGS) $(INC) -c $< 29 | 30 | clean: 31 | rm -f interp *.o 32 | rm -f tags 33 | 34 | ctags: 35 | ctags *.[ch] 36 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | PREREQUISITES 2 | ------------- 3 | Points2Grid requires the following to be installed - 4 | 5 | 1) curl: Please install libcurl from http://curl.haxx.se/. Points2Grid has 6 | been tested to work with version 7.20.0 of libcurl. 7 | 8 | 2) liblas: Please install liblas from http://liblas.org. Points2Grid has 9 | been tested to work with version 1.2.1 and 1.7+ of liblas. 10 | 11 | 3)gcc version 3.X. This Makefile doesn't work with GCC4. 12 | 13 | CONFIGURATION 14 | ------------- 15 | Please adjust the MEM_LIMIT variable in the Interpolation.h file to reflect 16 | the memory limitations of your system. As a rule of thumb, set the 17 | MEM_LIMIT to be (available memory in bytes)/55. For jobs that generate 18 | grids cells greater than the MEM_LIMIT, points2grid goes "out-of-core", 19 | resulting in significantly worse performance. Set the upper-bound on grid size in the MAKEFILE and modify the Makefile to point to your installation. 20 | 21 | COMPILATION 22 | ----------- 23 | 24 | If you have installed curl and liblas at non-standard locations, please set 25 | your CPLUS_INCLUDE_PATH and LIBRARY_PATH to respectively point to the 26 | locations of the include files and libraries of the installed software 27 | pre-requisites. 28 | 29 | If you are on a Mac (OSX), edit the Makefile to uncomment the Mac-specific 30 | CFLAGS setting. If you are on Solaris or Linux, there is no need to update 31 | the Makefile. 32 | 33 | To compile points2grid, simply use the Makefile by typing "make". The 34 | Makefile has been confirmed to work with gcc3 on Linux, Solaris and OSX. -------------------------------------------------------------------------------- /RELEASE_NOTES: -------------------------------------------------------------------------------- 1 | points2grid release notes 2 | 3 | Version 1.0.2: 4 | 5 | Version 1.0.2 of Points2Grid is a minor release, adding several small 6 | features to the prior 1.0.1 release. These include: 7 | 8 | * A compile-time option to align grids to the origin (0,0): Grids can now 9 | be aligned to origin, or to the lower-left corner of the dataset as in 10 | previous releases. 11 | 12 | * A compile-time option to set an upper-bound on grid size: Out-of-core 13 | operations have the possibility of exhausting all available disk space 14 | and crashing, with sufficiently high resolutions and large datasets. A 15 | suitable upper-limit on the number of grid points allowed in output can 16 | provide protection from this. With this option enabled, when the 17 | calculated grid size exceeds the pre-determined limit, Points2Grid will 18 | abort. 19 | 20 | * Support for libLAS 1.7+: Support for libLAS 1.7+, using the libLAS C 21 | API, has been back-ported from the CRREL fork of Points2Grid. Support for 22 | libLAS 1.2.1 and earlier through the native C++ API continues to be 23 | available as a compile-time option. 24 | 25 | Version 1.0.1: 26 | 27 | Version 1.0.1 of Points2Grid is a minor release, adding to the prior 1.0 release. 28 | Through the 1.0.1 release, Points2Grid is now available under an updated 4-clause BSD 29 | license. 30 | 31 | Version 1.0: 32 | 33 | * Input point clouds in ASCII and LAS formats 34 | * Outputs in Arc ASCII and GRD ASCII formats 35 | * DEM products including min, max, mean, and idw values 36 | * Point count values for every grid cell 37 | * Configurable search radius and grid resolution 38 | * Null filling, using a configurable moving window, to fill cells that have 39 | null values 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | COPYRIGHT AND LICENSE 2 | 3 | Copyright (c) 2011 The Regents of the University of California. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or 7 | without modification, are permitted provided that the following 8 | conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following 15 | disclaimer in the documentation and/or other materials provided 16 | with the distribution. 17 | 18 | 3. All advertising materials mentioning features or use of this 19 | software must display the following acknowledgement: This product 20 | includes software developed by the San Diego Supercomputer Center. 21 | 22 | 4. Neither the names of the Centers nor the names of the contributors 23 | may be used to endorse or promote products derived from this 24 | software without specific prior written permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 27 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 29 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 30 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 33 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 34 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 36 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 | POSSIBILITY OF SUCH DAMAGE. 38 | -------------------------------------------------------------------------------- /GridPoint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #ifndef _GRID_POINT_H_ 48 | #define _GRID_POINT_H_ 49 | 50 | typedef struct _GridPoint 51 | { 52 | double Zmin; 53 | double Zmax; 54 | double Zmean; 55 | unsigned int count; 56 | double Zidw; 57 | double sum; 58 | int empty; 59 | int filled; 60 | } GridPoint; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /Global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | */ 42 | 43 | #ifndef _GLOBAL_H_ 44 | #define _GLOBAL_H_ 45 | 46 | static const unsigned int OUTPUT_TYPE_MIN = 0x00000001; 47 | static const unsigned int OUTPUT_TYPE_MAX = 0x00000010; 48 | static const unsigned int OUTPUT_TYPE_MEAN = 0x00000100; 49 | static const unsigned int OUTPUT_TYPE_IDW = 0x00001000; 50 | static const unsigned int OUTPUT_TYPE_DEN = 0x00010000; 51 | static const unsigned int OUTPUT_TYPE_ALL = 0x00011111; 52 | 53 | enum OUTPUT_FORMAT { 54 | OUTPUT_FORMAT_ALL = 0, 55 | OUTPUT_FORMAT_ARC_ASCII, 56 | OUTPUT_FORMAT_GRID_ASCII, 57 | }; 58 | 59 | enum INPUT_FORMAT { 60 | INPUT_ASCII = 0, 61 | INPUT_LAS = 1, 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /GridFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #ifndef _GRID_FILE_H_ 48 | #define _GRID_FILE_H_ 49 | 50 | using namespace std; 51 | 52 | #include 53 | #include 54 | #include "GridPoint.h" 55 | 56 | class GridFile 57 | { 58 | public: 59 | GridFile(int id, char *_fname, int _size_x, int _size_y); 60 | ~GridFile(); 61 | 62 | int getId(); 63 | int map(); 64 | int unmap(); 65 | bool isInMemory(); 66 | unsigned int getMemSize(); 67 | 68 | GridPoint *interp; 69 | 70 | private: 71 | //ofstream fout; 72 | 73 | int filedes; 74 | int ID; 75 | int size_x; 76 | int size_y; 77 | bool inMemory; 78 | char fname[1024]; 79 | }; 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /CoreInterp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #ifndef _CORE_INTERP_H_ 48 | #define _CORE_INTERP_H_ 49 | 50 | class CoreInterp 51 | { 52 | public: 53 | CoreInterp() {}; 54 | virtual ~CoreInterp() {}; 55 | 56 | virtual int init() = 0; 57 | virtual int update(double data_x, double data_y, double data_z) = 0; 58 | virtual int finish(char *outputName, int outputFormat, unsigned int outputType) = 0; 59 | 60 | protected: 61 | double GRID_DIST_X; 62 | double GRID_DIST_Y; 63 | 64 | int GRID_SIZE_X; // total size of a grid 65 | int GRID_SIZE_Y; // 66 | 67 | // for outputting 68 | double min_x; 69 | double max_x; 70 | double min_y; 71 | double max_y; 72 | 73 | // for DEM filling 74 | int window_size; 75 | }; 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /GridMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #ifndef _GRID_MAP_H_ 48 | #define _GRID_MAP_H_ 49 | 50 | using namespace std; 51 | 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include "GridFile.h" 57 | 58 | class GridMap 59 | { 60 | public: 61 | GridMap(int _id, int _size_x, int _lower_bound, int _upper_bound, int _overlap_lower_bound, int _overlap_uuper_bound, bool _initialized, char * fname); 62 | ~GridMap(); 63 | 64 | public: 65 | int getId(); 66 | int getLowerBound(); 67 | int getUpperBound(); 68 | int getOverlapLowerBound(); 69 | int getOverlapUpperBound(); 70 | GridFile *getGridFile(); 71 | 72 | bool isInitialized(); 73 | 74 | void setId(int _id); 75 | void setLowerBound(int _lower_bound); 76 | void setUpperBound(int _upper_bound); 77 | void setOverlapLowerBound(int _overlap_lower_bound); 78 | void setOverlapUpperBound(int _overlap_upper_bound); 79 | void setInitialized(bool _initialized); 80 | 81 | private: 82 | int lowerBound; 83 | int upperBound; 84 | int overlapLowerBound; 85 | int overlapUpperBound; 86 | 87 | bool initialized; 88 | int id; 89 | GridFile * gridFile; 90 | }; 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /InCoreInterp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #ifndef _IN_CORE_INTERP_H_ 48 | #define _IN_CORE_INTERP_H_ 49 | 50 | using namespace std; 51 | 52 | #include 53 | #include "GridPoint.h" 54 | #include "CoreInterp.h" 55 | 56 | class InCoreInterp : public CoreInterp 57 | { 58 | public: 59 | InCoreInterp() {}; 60 | InCoreInterp(double dist_x, double dist_y, 61 | int size_x, int size_y, 62 | double r_sqr, 63 | double _min_x, double _max_x, 64 | double _min_y, double _max_y, 65 | int _window_size); 66 | ~InCoreInterp(); 67 | 68 | virtual int init(); 69 | virtual int update(double data_x, double data_y, double data_z); 70 | virtual int finish(char *outputName, int outputFormat, unsigned int outputType); 71 | 72 | private: 73 | GridPoint **interp; 74 | double radius_sqr; 75 | 76 | private: 77 | void update_first_quadrant(double data_z, int base_x, int base_y, double x, double y); 78 | void update_second_quadrant(double data_z, int base_x, int base_y, double x, double y); 79 | void update_third_quadrant(double data_z, int base_x, int base_y, double x, double y); 80 | void update_fourth_quadrant(double data_z, int base_x, int base_y, double x, double y); 81 | 82 | void updateGridPoint(int x, int y, double data_z, double distance); 83 | void printArray(); 84 | int outputFile(char *outputName, int outputFormat, unsigned int outputType); 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![NSF-0930731](https://img.shields.io/badge/NSF-0930731-blue.svg)](https://nsf.gov/awardsearch/showAward?AWD_ID=0930731) 2 | 3 | Points2Grid 4 | ------------ 5 | 6 | Proven through thousands of jobs run via the OpenTopography Facility 7 | (http://www.opentopography.org), Points2Grid is a robust and scalable tool 8 | that generates Digital Elevation Models (DEM) using a local gridding 9 | method. The local gridding algorithm computes grid cell elevation using a 10 | circular neighbourhood defined around each grid cell based on a radius 11 | provided by the user. This neighbourhood is referred to as a bin, while the 12 | grid cell is referred to as a DEM node. Up to four values — minimum, 13 | maximum, mean, or inverse distance weighted (IDW) mean — are computed for 14 | points that fall within the bin. These values are then assigned to the 15 | corresponding DEM node and used to represent the elevation variation over 16 | the neighbourhood represented by the bin. If no points are found within a 17 | given bin, the DEM node receives a value of null. The Points2Grid service 18 | also provides a null filing option, which applies an inverse distance 19 | weighted focal mean via a square moving window of 3, 5, or 7 pixels to fill 20 | cells in the DEM that have null values. 21 | The local gridding approach employed by 22 | Points2Grid is most effective in situations where LIDAR shot densities 23 | exceed the resolution of the grid to be produced from these data. 24 | Please direct all feedback to info@opentopography.org 25 | 26 | 27 | INSTALLATION 28 | ------------ 29 | Please read the INSTALL file for details on the installation process. 30 | 31 | USE 32 | --- 33 | If your pre-requisites (curl and liblas) are installed on non-standard 34 | location, please set your LD_LIBRARY_PATH accordingly. To run complete 35 | usage information, please type "points2grid" from the command-line. The 36 | command-line options are as follows: 37 | 38 | % ./interp [-i | -l ] -o 39 | [--input_format=ascii|las] [--all] [--min] [--max] 40 | [--mean] [--idw] [--den] [--fill|--fill_window_size=] [-r 41 | ] [--output_format=all|arc|grid] 42 | [--resolution=|--resolution-x=|--resolution-y=] 43 | 44 | 1. -i | -l : 45 | - must be unzipped plain text file 46 | 47 | 2. -o : 48 | - without extension, i.e. if you want the output file to be 49 | test.asc, this parameter shoud be "test" 50 | 51 | 3. Output Type: 52 | --min: the Zmin values are stored 53 | --max: the Zmax values are stored 54 | --mean: the Zmean values are stored 55 | --idw: the Zidw values are stored 56 | --den: the density values are stored 57 | --all (default): all the values are stored 58 | 59 | 4. -r 60 | - specifies the search radius. The default value is square root 2 61 | of horizontal distance in a grid cell 62 | 63 | 5. --input_format: 64 | - 'ascii' expects input point cloud in ASCII format (default) 65 | - 'las' expects input point cloud in LAS format 66 | 67 | 6. --output_format: 68 | - 'all' generates every possible format, 69 | - 'arc' for ArcGIS format, 70 | - 'grid' for Ascii GRID format, 71 | - the default value is --all 72 | 73 | 7. Resolution 74 | - --resolution=: The resolution is set to the specified 75 | value. Use square grids. 76 | - --resolution-x= --resolution-y=: Each parameter 77 | specifies each side of grid cells. 78 | - If not specified, default values (6ft) are used. 79 | 80 | 8. Null Filling 81 | --fill: fills nulls in the DEM. Default window size is 3. 82 | --fill_window_size=: The fill window is set to value. 83 | Permissible values are 3, 5 and 7. 84 | -------------------------------------------------------------------------------- /Interpolation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | 41 | Local Interpolation Implementation 42 | 43 | 1. Grid file index structure 44 | 2. Out-of-core Implementation 45 | 3. no streaming 46 | 4. no parallelization 47 | 48 | * 49 | * 50 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 51 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 52 | * 53 | */ 54 | 55 | #ifndef _INTERP_H_ 56 | #define _INTERP_H_ 57 | 58 | #include 59 | #include 60 | 61 | using namespace std; 62 | 63 | #include "GridPoint.h" 64 | #include "CoreInterp.h" 65 | #include "OutCoreInterp.h" 66 | #include "InCoreInterp.h" 67 | 68 | enum coreMode 69 | { 70 | INCORE = 0, 71 | OUTCORE 72 | }; 73 | 74 | //class GridPoint; 75 | 76 | class Interpolation 77 | { 78 | public: 79 | Interpolation(double x_dist, double y_dist, double radius, int _window_size); 80 | ~Interpolation(); 81 | 82 | int init(char *inputName, int inputFormat); 83 | 84 | int interpolation(char *inputName, char *outputName, int inputFormat, 85 | int outputFormat, unsigned int type); 86 | 87 | unsigned int getDataCount(); 88 | 89 | unsigned int getGridSizeX(); 90 | unsigned int getGridSizeY(); 91 | 92 | // for debug 93 | void printArray(); 94 | 95 | // depricated 96 | void setRadius(double r); 97 | 98 | public: 99 | double GRID_DIST_X; 100 | double GRID_DIST_Y; 101 | 102 | static const int MAX_POINT_SIZE = 16000000; 103 | static const double WEIGHTER = 2.0; 104 | static const unsigned int MEM_LIMIT = 200000000; 105 | 106 | private: 107 | 108 | double min_x; 109 | double min_y; 110 | double max_x; 111 | double max_y; 112 | 113 | unsigned int GRID_SIZE_X; 114 | unsigned int GRID_SIZE_Y; 115 | 116 | unsigned int data_count; 117 | double radius_sqr; 118 | int window_size; 119 | 120 | int core_mode; 121 | 122 | CoreInterp *interp; 123 | }; 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /GridMap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #include "GridMap.h" 48 | #include 49 | 50 | 51 | 52 | 53 | GridMap::GridMap(int _id, int _size_x, int _lower_bound, int _upper_bound, int _overlap_lower_bound, int _overlap_upper_bound, bool _initialized, char *fname) 54 | { 55 | id = _id; 56 | lowerBound = _lower_bound; 57 | upperBound = _upper_bound; 58 | overlapLowerBound = _overlap_lower_bound; 59 | overlapUpperBound = _overlap_upper_bound; 60 | initialized = _initialized; 61 | 62 | gridFile = new GridFile(id, fname, _size_x, _overlap_upper_bound - _overlap_lower_bound + 1); 63 | } 64 | GridMap::~GridMap() 65 | { 66 | if(gridFile != NULL) 67 | delete gridFile; 68 | } 69 | 70 | int GridMap::getLowerBound() 71 | { 72 | return lowerBound; 73 | } 74 | int GridMap::getUpperBound() 75 | { 76 | return upperBound; 77 | } 78 | int GridMap::getOverlapLowerBound() 79 | { 80 | return overlapLowerBound; 81 | } 82 | int GridMap::getOverlapUpperBound() 83 | { 84 | return overlapUpperBound; 85 | } 86 | 87 | bool GridMap::isInitialized() 88 | { 89 | return initialized; 90 | } 91 | int GridMap::getId() 92 | { 93 | return id; 94 | } 95 | GridFile *GridMap::getGridFile() 96 | { 97 | return gridFile; 98 | } 99 | 100 | void GridMap::setLowerBound(int _lower_bound) 101 | { 102 | lowerBound = _lower_bound; 103 | } 104 | void GridMap::setUpperBound(int _upper_bound) 105 | { 106 | upperBound = _upper_bound; 107 | } 108 | void GridMap::setOverlapLowerBound(int _overlap_lower_bound) 109 | { 110 | overlapLowerBound = _overlap_lower_bound; 111 | } 112 | void GridMap::setOverlapUpperBound(int _overlap_upper_bound) 113 | { 114 | overlapUpperBound = _overlap_upper_bound; 115 | } 116 | void GridMap::setInitialized(bool _initialized) 117 | { 118 | initialized = _initialized; 119 | } 120 | void GridMap::setId(int _id) 121 | { 122 | id = _id; 123 | } 124 | 125 | 126 | -------------------------------------------------------------------------------- /OutCoreInterp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #ifndef _OUT_CORE_INTERP_H_ 48 | #define _OUT_CORE_INTERP_H_ 49 | 50 | using namespace std; 51 | 52 | #include "CoreInterp.h" 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include "GridPoint.h" 58 | #include "GridMap.h" 59 | 60 | class UpdateInfo; 61 | 62 | class OutCoreInterp : public CoreInterp 63 | { 64 | public: 65 | OutCoreInterp() {}; 66 | OutCoreInterp(double dist_x, double dist_y, 67 | int size_x, int size_y, 68 | double r_sqr, 69 | double _min_x, double _max_x, 70 | double _min_y, double _max_y, 71 | int _window_size); 72 | ~OutCoreInterp(); 73 | 74 | virtual int init(); 75 | virtual int update(double data_x, double data_y, double data_z); 76 | virtual int finish(char *outputName, int outputFormat, unsigned int outputType); 77 | 78 | private: 79 | void updateInterpArray(int fileNum, double data_x, double data_y, double data_z); 80 | void update_first_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y); 81 | void update_second_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y); 82 | void update_third_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y); 83 | void update_fourth_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y); 84 | 85 | void updateGridPoint(int fileNum, int x, int y, double data_z, double distance); 86 | int findFileNum(double data_y); 87 | void finalize(); 88 | int outputFile(char *outputName, int outputFormat, unsigned int outputType); 89 | 90 | 91 | public: 92 | static const unsigned int QUEUE_LIMIT = 1000; 93 | 94 | private: 95 | double radius_sqr; 96 | 97 | int overlapSize; 98 | int local_grid_size_x; 99 | int local_grid_size_y; 100 | 101 | int numFiles; 102 | list *qlist; 103 | GridMap **gridMap; 104 | int openFile; 105 | }; 106 | 107 | class UpdateInfo 108 | { 109 | public: 110 | UpdateInfo() : data_x(0), data_y(0), data_z(0) {}; 111 | UpdateInfo(double x, double y, double z) : data_x(x), data_y(y), data_z(z){}; 112 | 113 | public: 114 | double data_x; 115 | double data_y; 116 | double data_z; 117 | }; 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /GridFile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #include "GridFile.h" 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | GridFile::GridFile(int id, char *_fname, int _size_x, int _size_y) 58 | { 59 | FILE *fp; 60 | size_t n = 0; 61 | 62 | ID = id; 63 | strncpy(fname, _fname, sizeof(fname)); 64 | size_x = _size_x; 65 | size_y = _size_y; 66 | inMemory = false; 67 | 68 | if((fp = fopen64(fname, "w+")) == NULL) 69 | { 70 | fprintf(stderr, "%s fopen error %d(%s) \n", fname, errno, strerror(errno)); 71 | } 72 | 73 | GridPoint init_value = {DBL_MAX, -DBL_MAX, 0, 0, 0, 0, 0, 0}; 74 | 75 | for(int i = 0; i < size_x * size_y; i++) 76 | n += fwrite(&init_value, sizeof(GridPoint), 1, fp); 77 | 78 | cout << id << ". file size: " << n * sizeof(GridPoint) << endl; 79 | fclose(fp); 80 | 81 | } 82 | 83 | GridFile::~GridFile() 84 | { 85 | if(inMemory == true){ 86 | munmap(interp, sizeof(GridPoint) * size_x * size_y); 87 | inMemory = false; 88 | interp = NULL; 89 | } 90 | 91 | if(filedes >= 0) 92 | close(filedes); 93 | 94 | unlink(fname); 95 | } 96 | 97 | int GridFile::getId() 98 | { 99 | return ID; 100 | } 101 | 102 | // memory map 103 | int GridFile::map() 104 | { 105 | if((filedes = open(fname, O_RDWR)) < 0) 106 | { 107 | fprintf(stderr, "%s open error %d(%s)\n", fname, errno, strerror(errno)); 108 | } 109 | 110 | if((interp = (GridPoint *)mmap(0, sizeof(GridPoint) * size_x * size_y, PROT_READ | PROT_WRITE, MAP_SHARED, filedes, 0)) == MAP_FAILED) 111 | { 112 | fprintf(stderr, "mmap error %d(%s) \n", errno, strerror(errno)); 113 | return -1; 114 | } 115 | inMemory = true; 116 | 117 | return 0; 118 | } 119 | 120 | int GridFile::unmap() 121 | { 122 | int rc; 123 | 124 | if(interp != NULL) 125 | { 126 | rc = munmap(interp, sizeof(GridPoint) * size_x * size_y); 127 | 128 | if(rc < 0) 129 | { 130 | fprintf(stderr, "munmap error %d(%s)\n", errno, strerror(errno)); 131 | return -1; 132 | } 133 | 134 | inMemory = false; 135 | interp = NULL; 136 | close(filedes); 137 | filedes = -1; 138 | 139 | } 140 | 141 | return 0; 142 | } 143 | 144 | bool GridFile::isInMemory() 145 | { 146 | return inMemory; 147 | } 148 | 149 | unsigned int GridFile::getMemSize() 150 | { 151 | return size_x * size_y * sizeof(GridPoint); 152 | } 153 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * LIDAR DEM Generation 43 | * This program takes a set of randomly distributed points (ASCII or LAS) 44 | * as input, and generates gridded points (DEM) 45 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 46 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 47 | * 48 | */ 49 | 50 | /* 51 | 52 | * 53 | * FileName: main.cpp 54 | * Author: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 55 | * Description: this program starts from this file 56 | * 57 | */ 58 | 59 | #include "Interpolation.h" 60 | #include "Global.h" 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | void printUsage(); 71 | 72 | 73 | int main(int argc, char **argv) 74 | { 75 | //struct tms tbuf; 76 | clock_t t0, t1; 77 | 78 | // parameters 79 | char inputName[1024] = {0}; 80 | char inputURL[2048] = {0}; 81 | char outputName[1024] = {0}; 82 | int input_format = INPUT_ASCII; 83 | int output_format = 0; 84 | unsigned int type = 0x00000000; 85 | double GRID_DIST_X = 6.0; 86 | double GRID_DIST_Y = 6.0; 87 | double searchRadius = (double) sqrt(2.0) * GRID_DIST_X; 88 | int window_size = 0; 89 | 90 | if(argc < 5) 91 | { 92 | printUsage(); 93 | exit(0); 94 | } 95 | 96 | // argument processing.. 97 | while(1) 98 | { 99 | static struct option long_options[] = 100 | { 101 | {"output_format", 1, 0, 0}, 102 | {"resolution", 1, 0, 0}, 103 | {"resolution-x", 1, 0, 0}, 104 | {"resolution-y", 1, 0, 0}, 105 | {"min", 0, 0, 0}, 106 | {"max", 0, 0, 0}, 107 | {"mean", 0, 0, 0}, 108 | {"idw", 0, 0, 0}, 109 | {"den", 0, 0, 0}, 110 | {"all", 0, 0, 0}, 111 | {"fill", 0, 0, 0}, 112 | {"fill_window_size", 1, 0, 0}, 113 | {"input_format", 1, 0, 0}, 114 | {0, 0, 0, 0} 115 | }; 116 | 117 | int option_index = 0; 118 | 119 | int c = getopt_long(argc, argv, "i:o:r:l:", long_options, &option_index); 120 | 121 | if(c == -1) 122 | break; 123 | 124 | switch(c) 125 | { 126 | case 0: 127 | 128 | switch(option_index) 129 | { 130 | case 0: 131 | if(!strncmp(optarg, "all", strlen("all"))) 132 | output_format = OUTPUT_FORMAT_ALL; 133 | else if(!strncmp(optarg, "arc", strlen("arc"))) 134 | output_format = OUTPUT_FORMAT_ARC_ASCII; 135 | else if(!strncmp(optarg, "grid", strlen("grid"))) 136 | output_format = OUTPUT_FORMAT_GRID_ASCII; 137 | else{ 138 | printUsage(); 139 | exit(0); 140 | } 141 | break; 142 | 143 | case 1: 144 | if(optarg != NULL){ 145 | GRID_DIST_X = atof(optarg); 146 | GRID_DIST_Y = atof(optarg); 147 | if(searchRadius == sqrt(2.0) * 6.0) 148 | searchRadius = (double) sqrt(2.0) * GRID_DIST_X; 149 | 150 | if(GRID_DIST_X == 0){ 151 | printUsage(); 152 | exit(0); 153 | } 154 | }else{ 155 | printUsage(); 156 | exit(0); 157 | } 158 | 159 | case 2: 160 | if(optarg != NULL){ 161 | GRID_DIST_X = atof(optarg); 162 | if(searchRadius == sqrt(2.0) * 6.0) 163 | searchRadius = (double) sqrt(2.0) * GRID_DIST_X; 164 | 165 | if(GRID_DIST_X == 0){ 166 | printUsage(); 167 | exit(0); 168 | } 169 | }else{ 170 | printUsage(); 171 | exit(0); 172 | } 173 | break; 174 | 175 | case 3: 176 | if(optarg != NULL){ 177 | GRID_DIST_Y = atof(optarg); 178 | if(GRID_DIST_Y == 0){ 179 | printUsage(); 180 | exit(0); 181 | } 182 | }else{ 183 | printUsage(); 184 | exit(0); 185 | } 186 | break; 187 | 188 | case 4: 189 | type |= OUTPUT_TYPE_MIN; 190 | break; 191 | case 5: 192 | type |= OUTPUT_TYPE_MAX; 193 | break; 194 | case 6: 195 | type |= OUTPUT_TYPE_MEAN; 196 | break; 197 | case 7: 198 | type |= OUTPUT_TYPE_IDW; 199 | break; 200 | case 8: 201 | type |= OUTPUT_TYPE_DEN; 202 | break; 203 | case 9: 204 | type = OUTPUT_TYPE_ALL; 205 | break; 206 | 207 | case 10: 208 | window_size = 3; 209 | break; 210 | case 11: 211 | if(optarg != NULL){ 212 | window_size = atoi(optarg); 213 | if(!((window_size == 3) || (window_size == 5) || (window_size == 7))) { 214 | printUsage(); 215 | exit(0); 216 | } 217 | }else{ 218 | printUsage(); 219 | exit(0); 220 | } 221 | break; 222 | case 12: 223 | if(!strncmp(optarg, "ascii", strlen("ascii"))) 224 | input_format = INPUT_ASCII; 225 | else if(!strncmp(optarg, "las", strlen("las"))) 226 | input_format = INPUT_LAS; 227 | else{ 228 | printUsage(); 229 | exit(0); 230 | } 231 | break; 232 | 233 | default: 234 | printUsage(); 235 | exit(0); 236 | } 237 | 238 | break; 239 | case 'i': 240 | 241 | if(optarg != NULL) 242 | strncpy(inputName, optarg, sizeof(inputName)); 243 | else{ 244 | printUsage(); 245 | exit(0); 246 | } 247 | 248 | break; 249 | case 'l': 250 | 251 | if(optarg != NULL) 252 | strncpy(inputURL, optarg, sizeof(inputURL)); 253 | else{ 254 | printUsage(); 255 | exit(0); 256 | } 257 | 258 | break; 259 | case 'o': 260 | if(optarg != NULL) 261 | strncpy(outputName, optarg, sizeof(inputName)); 262 | else{ 263 | printUsage(); 264 | exit(0); 265 | } 266 | 267 | break; 268 | case 'r': 269 | if(optarg != NULL) 270 | searchRadius = atof(optarg); 271 | 272 | break; 273 | default: 274 | printUsage(); 275 | exit(0); 276 | } 277 | } 278 | if(type == 0) 279 | type = OUTPUT_TYPE_ALL; 280 | 281 | if(((inputName == NULL || !strcmp(inputName, "")) && 282 | (inputURL == NULL || !strcmp(inputURL, ""))) 283 | || 284 | (outputName == NULL || !strcmp(outputName, ""))) 285 | { 286 | printUsage(); 287 | exit(0); 288 | } 289 | 290 | // download file from URL, and set input name 291 | if (!((inputURL == NULL || !strcmp(inputURL, "")))) { 292 | CURL *curl; 293 | CURLcode res; 294 | 295 | /* get the file name from the URL */ 296 | int i = 0; 297 | for(i = sizeof(inputURL); i>= 0; i--) { 298 | if(inputURL[i] == '/') 299 | break; 300 | } 301 | strncpy(inputName, inputURL+i+1, sizeof(inputName)); 302 | 303 | curl = curl_easy_init(); 304 | if (!curl) { 305 | cout << "Can't initialize curl object to download input from: " 306 | << inputURL << endl; 307 | exit(1); 308 | } 309 | 310 | /* set URL */ 311 | curl_easy_setopt(curl, CURLOPT_URL, inputURL); 312 | curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); 313 | 314 | /* and write to file */ 315 | FILE *fp; 316 | fp = fopen(inputName, "w"); 317 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 318 | 319 | /* perform the curl request and clean up */ 320 | res = curl_easy_perform(curl); 321 | curl_easy_cleanup(curl); 322 | fclose(fp); 323 | 324 | if (res != 0) { 325 | cout << "Error while downloading input from: " << inputURL << endl; 326 | exit(1); 327 | } 328 | 329 | } 330 | 331 | cout << "Parameters ************************" << endl; 332 | cout << "inputName: '" << inputName << "'" << endl; 333 | cout << "input_format: " << input_format << endl; 334 | cout << "outputName: '" << outputName << "'" << endl; 335 | cout << "GRID_DIST_X: " << GRID_DIST_X << endl; 336 | cout << "GRID_DIST_Y: " << GRID_DIST_Y << endl; 337 | cout << "searchRadius: " << searchRadius << endl; 338 | cout << "output_format: " << output_format << endl; 339 | cout << "type: " << type << endl; 340 | cout << "fill window size: " << window_size << endl; 341 | cout << "************************************" << endl; 342 | 343 | t0 = clock(); 344 | //t0 = times(&tbuf); 345 | 346 | Interpolation *ip = new Interpolation(GRID_DIST_X, GRID_DIST_Y, searchRadius, window_size); 347 | 348 | if(ip->init(inputName, input_format) < 0) 349 | { 350 | fprintf(stderr, "Interpolation::init() error\n"); 351 | return -1; 352 | } 353 | 354 | t1 = clock(); 355 | //t1 = times(&tbuf); 356 | printf("Init + Min/Max time: %10.2f\n", (double)(t1 - t0)/CLOCKS_PER_SEC); 357 | 358 | t0 = clock(); 359 | //t0 = times(&tbuf); 360 | 361 | if(ip->interpolation(inputName, outputName, input_format, output_format, type) < 0) 362 | { 363 | fprintf(stderr, "Interpolation::interpolation() error\n"); 364 | return -1; 365 | } 366 | 367 | t1 = clock(); 368 | //t1 = times(&tbuf); 369 | printf("Interpolation + Output time: %10.2f\n", (double)(t1 - t0)/CLOCKS_PER_SEC); 370 | 371 | 372 | //printf("i: %d\n", i); 373 | printf("# of data: %d\n", ip->getDataCount()); 374 | //printf("Total Execution time: %10.2f\n", (t1 - t0)/(double) sysconf(_SC_CLK_TCK)); 375 | printf("dimension: %d x %d\n", ip->getGridSizeX(), ip->getGridSizeY()); 376 | 377 | delete ip; 378 | 379 | return 0; 380 | } 381 | 382 | void printUsage() 383 | { 384 | cout << "*****************************************************" << endl; 385 | cout << "Usage: \n" << endl; 386 | cout << "% ./interp [-i | -l ] -o [--input_format=ascii|las] [--all] [--min] [--max] [--mean] [--idw] [--den] [--fill|--fill_window_size=] [-r ] [--output_format=all|arc|grid] [--resolution=|--resolution-x=|--resolution-y=] "<< endl << endl; 387 | cout << "1. -i | -l :"<< endl; 388 | cout << " - must be unzipped plain text file"<< endl << endl; 389 | cout << "2. -o : "<< endl; 390 | cout << " - without extension, i.e. if you want the output file to be test.asc, this parameter shoud be \"test\""<< endl << endl; 391 | cout << "3. Output Type: " << endl; 392 | cout << " --min: the Zmin values are stored" << endl; 393 | cout << " --max: the Zmax values are stored" << endl; 394 | cout << " --mean: the Zmean values are stored" << endl; 395 | cout << " --idw: the Zidw values are stored" << endl; 396 | cout << " --den: the density values are stored" << endl; 397 | cout << " --all (default): all the values are stored" << endl << endl; 398 | cout << "4. -r "<< endl; 399 | cout << " - specifies the search radius. The default value is square root 2 of horizontal distance in a grid cell"<< endl << endl; 400 | cout << "5. --input_format: "<< endl; 401 | cout << " - 'ascii' expects input point cloud in ASCII format (default)"<< endl; 402 | cout << " - 'las' expects input point cloud in LAS format"<< endl << endl; 403 | cout << "6. --output_format: "<< endl; 404 | cout << " - 'all' generates every possible format, "<< endl; 405 | cout << " - 'arc' for ArcGIS format, "<< endl; 406 | cout << " - 'grid' for Ascii GRID format, "<< endl; 407 | cout << " - the default value is --all"<< endl << endl; 408 | cout << "7. Resolution"<< endl; 409 | cout << " - --resolution=: The resolution is set to the specified value. Use square grids."<< endl; 410 | cout << " - --resolution-x= --resolution-y=: Each parameter specifies each side of grid cells."<< endl; 411 | cout << " - If not specified, default values (6ft) are used."<< endl << endl; 412 | cout << "8. Null Filling"<: The fill window is set to value. Permissible values are 3, 5 and 7."< 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include // std::ifstream 59 | #include // std::cout 60 | #ifdef USE_LIBLAS_17 61 | //if binding against liblas 1.7+ API, use C API calls 62 | //(backported from CRREL codebase) 63 | extern "C" { 64 | #include // the C API is stable across liblas versions 65 | } 66 | #else 67 | //use liblas 1.2.1 C++ API by default 68 | #include 69 | #include 70 | #endif 71 | 72 | 73 | ///////////////////////////////////////////////////////////// 74 | // Public Methods 75 | ///////////////////////////////////////////////////////////// 76 | 77 | //x_dist and y_dist represent length and height of each grid cell (resolution) 78 | //radius represents search radius. 79 | //window size represents fill window size 80 | Interpolation::Interpolation(double x_dist, double y_dist, double radius, int _window_size) : GRID_DIST_X (x_dist), GRID_DIST_Y(y_dist) 81 | { 82 | data_count = 0; 83 | radius_sqr = radius * radius; 84 | window_size = _window_size; 85 | 86 | min_x = DBL_MAX; 87 | min_y = DBL_MAX; 88 | 89 | max_x = -DBL_MAX; 90 | max_y = -DBL_MAX; 91 | } 92 | 93 | Interpolation::~Interpolation() 94 | { 95 | delete interp; 96 | } 97 | 98 | int Interpolation::init(char *inputName, int inputFormat) 99 | { 100 | clock_t t0, t1; 101 | 102 | 103 | ////////////////////////////////////////////////////////////////////// 104 | // MIN/MAX SEARCHING 105 | // TODO: the size of data, min, max of each coordinate 106 | // are required to implement streaming processing.... 107 | // 108 | // This code can be eliminated if database can provide these values 109 | ////////////////////////////////////////////////////////////////////// 110 | 111 | t0 = clock(); 112 | 113 | if(inputName == NULL) 114 | { 115 | cout << "Wrong Input File Name" << endl; 116 | return -1; 117 | } 118 | 119 | printf("inputName: '%s'\n", inputName); 120 | 121 | if (inputFormat == INPUT_ASCII) { 122 | FILE *fp; 123 | char line[1024]; 124 | double data_x, data_y; 125 | //double data_z; 126 | 127 | if((fp = fopen64(inputName, "r")) == NULL) 128 | { 129 | cout << "file open error" << endl; 130 | return -1; 131 | } 132 | 133 | // throw the first line away - it contains the header 134 | fgets(line, sizeof(line), fp); 135 | 136 | // read the data points to find min and max values 137 | while(fgets(line, sizeof(line), fp) != NULL) 138 | { 139 | data_x = atof(strtok(line, ",\n")); 140 | if(min_x > data_x) min_x = data_x; 141 | if(max_x < data_x) max_x = data_x; 142 | 143 | data_y = atof(strtok(NULL, ",\n")); 144 | if(min_y > data_y) min_y = data_y; 145 | if(max_y < data_y) max_y = data_y; 146 | 147 | data_count++; 148 | } 149 | 150 | fclose(fp); 151 | } else { // las input 152 | 153 | #ifdef USE_LIBLAS_17 154 | LASReaderH lr = LASReader_Create(inputName); 155 | if (!lr) { 156 | LASError_Print("Could not open file to read."); 157 | return -1; 158 | } 159 | 160 | LASHeaderH lh = LASReader_GetHeader(lr); 161 | if (!lh) { 162 | LASError_Print("error while reading LAS file: verify that the input is valid LAS file."); 163 | LASReader_Destroy(lr); 164 | return -1; 165 | } 166 | 167 | min_x = LASHeader_GetMinX(lh); 168 | min_y = LASHeader_GetMinY(lh); 169 | max_x = LASHeader_GetMaxX(lh); 170 | max_y = LASHeader_GetMaxY(lh); 171 | data_count = LASHeader_GetPointRecordsCount(lh); 172 | 173 | LASReader_Destroy(lr); 174 | #else 175 | try { 176 | std::ifstream ifs; 177 | ifs.open(inputName, std::ios::in | std::ios::binary); 178 | 179 | // create a las file reader 180 | liblas::LASReader reader(ifs); 181 | 182 | /// get header information 183 | liblas::LASHeader const& header = reader.GetHeader(); 184 | 185 | min_x = header.GetMinX(); 186 | min_y = header.GetMinY(); 187 | max_x = header.GetMaxX(); 188 | max_y = header.GetMaxY(); 189 | data_count = header.GetPointRecordsCount(); 190 | 191 | ifs.close(); 192 | } catch (std::runtime_error &e) { 193 | cout << "error while reading LAS file: verify that the input is valid LAS file" << endl; 194 | return -1; 195 | } 196 | #endif 197 | } 198 | 199 | t1 = clock(); 200 | printf("Min/Max searching time: %10.2f\n", (double)(t1 - t0)/CLOCKS_PER_SEC); 201 | 202 | 203 | 204 | ////////////////////////////////////////////////////////////////////// 205 | // Intialization Step excluding min/max searching 206 | ////////////////////////////////////////////////////////////////////// 207 | /* 208 | for(i = 0; i < data_count; i++) 209 | { 210 | arrX[i] -= min_x; 211 | arrY[i] -= min_y; 212 | //printf("%f,%f,%f\n", arrX[i] , arrY[i] ,arrZ[i]); 213 | } 214 | */ 215 | 216 | #ifdef ALIGN_ORIGIN 217 | cout.flags ( ios::fixed); 218 | cout.width (10); 219 | 220 | cout << "Bounding Box:\t(" << min_x << ", " << min_y << "), (" << max_x << ", " << max_y << ")\n"; 221 | 222 | //a bounding box/grid based on min/max x and y values is not likely to be aligned to origin. 223 | //to align to origin, the origin must be a grid point, and all other grid points must be 224 | //multiples of the grid resolution (GRID_DIST_X/Y). 225 | 226 | //By default, p2g makes the lower-left corner of the bounding box of the points (min_x, min_y) 227 | //the lower-left corner of the grid, and the upper-right corner of the grid will be some multiple 228 | //of GRID_DISTX/Y that will encompass (max_x,max_y). 229 | 230 | //We align the grid to origin by extending the lower-left corner of the bounding box south-west 231 | //until it aligns with the closest grid-point. The new lower-left corner will become the new min_x, min_y. 232 | //this works because min/max values are only used to determine the size of the grid; interp does not 233 | //require a point to exist at min_x and/or min_y. Also, because interp iterates through the point-cloud, 234 | //padding the grid does not impact DEM generation time. 235 | 236 | min_x = floor(min_x/GRID_DIST_X) * GRID_DIST_X; 237 | min_y = floor(min_y/GRID_DIST_Y) * GRID_DIST_Y; 238 | 239 | //max_x and max_y record the true upper-right boundary of the point-cloud and are not similarly padded. 240 | //The upper-right corner of the grid will be aligned to origin, being an multiple of GRID_DIST_X/Y. 241 | GRID_SIZE_X = (int)((max_x - min_x)/GRID_DIST_X) + 1; 242 | GRID_SIZE_Y = (int)((max_y - min_y)/GRID_DIST_Y) + 1; 243 | 244 | double grid_max_x = GRID_SIZE_X * GRID_DIST_X + min_x; 245 | double grid_max_y = GRID_SIZE_Y * GRID_DIST_Y + min_y; 246 | 247 | cout << "Aligned Grid:\t(" << min_x << ", " << min_y << "), (" << grid_max_x << ", " << grid_max_y << ")\n"; 248 | #else 249 | cout << "ORIGINAL\tmin_x: " << min_x << ", max_x: " << max_x << ", min_y: " << min_y << ", max_y: " << max_y << endl; 250 | GRID_SIZE_X = (int)((max_x - min_x)/GRID_DIST_X) + 1; 251 | GRID_SIZE_Y = (int)((max_y - min_y)/GRID_DIST_Y) + 1; 252 | #endif 253 | 254 | cout << "GRID_SIZE_X " << GRID_SIZE_X << endl; 255 | cout << "GRID_SIZE_Y " << GRID_SIZE_Y << endl; 256 | cout << "NUMBER OF GRID POINTS: " << GRID_SIZE_X * GRID_SIZE_Y << "\n"; 257 | 258 | #ifdef HARD_LIMIT 259 | if((GRID_SIZE_X * GRID_SIZE_Y) > HARD_LIMIT) 260 | { 261 | cout << "size of grid exceeds hard limit. Aborting...\n"; 262 | return -1; 263 | } 264 | #endif 265 | 266 | 267 | // if the size is too big to fit in memory, 268 | // then construct out-of-core structure 269 | if(GRID_SIZE_X * GRID_SIZE_Y > MEM_LIMIT) 270 | { 271 | core_mode = OUTCORE; 272 | 273 | interp = new OutCoreInterp(GRID_DIST_X, GRID_DIST_Y, GRID_SIZE_X, GRID_SIZE_Y, radius_sqr, min_x, max_x, min_y, max_y, window_size); 274 | if(interp == NULL) 275 | { 276 | cout << "OutCoreInterp construction error" << endl; 277 | return -1; 278 | } 279 | 280 | cout << "Interpolation uses out-of-core algorithm" << endl; 281 | 282 | // else 283 | // do normal 284 | } else { 285 | core_mode = INCORE; 286 | 287 | interp = new InCoreInterp(GRID_DIST_X, GRID_DIST_Y, GRID_SIZE_X, GRID_SIZE_Y, radius_sqr, min_x, max_x, min_y, max_y, window_size); 288 | 289 | cout << "Interpolation uses in-core algorithm" << endl; 290 | } 291 | 292 | if(interp->init() < 0) 293 | { 294 | cout << "inter->init() error" << endl; 295 | return -1; 296 | } 297 | 298 | cout << "Interpolation::init() done successfully" << endl; 299 | 300 | 301 | return 0; 302 | } 303 | 304 | int Interpolation::interpolation(char *inputName, 305 | char *outputName, 306 | int inputFormat, 307 | int outputFormat, 308 | unsigned int outputType) 309 | { 310 | int rc; 311 | //unsigned int i; 312 | double data_x, data_y; 313 | double data_z; 314 | 315 | 316 | printf("Interpolation Starts\n"); 317 | 318 | if (inputFormat == INPUT_ASCII) { 319 | FILE *fp; 320 | char line[1024]; 321 | 322 | if((fp = fopen64(inputName, "r")) == NULL) 323 | { 324 | printf("file open error\n"); 325 | return -1; 326 | } 327 | 328 | // throw the first line away - it contains the header 329 | fgets(line, sizeof(line), fp); 330 | 331 | // read every point and generate DEM 332 | while(fgets(line, sizeof(line), fp) != NULL) 333 | { 334 | data_x = atof(strtok(line, ",\n")); 335 | data_y = atof(strtok(NULL, ",\n")); 336 | data_z = atof(strtok(NULL, ",\n")); 337 | 338 | data_x -= min_x; 339 | data_y -= min_y; 340 | 341 | //if((rc = interp->update(arrX[i], arrY[i], arrZ[i])) < 0) 342 | if((rc = interp->update(data_x, data_y, data_z)) < 0) 343 | { 344 | cout << "interp->update() error while processing " << endl; 345 | return -1; 346 | } 347 | } 348 | 349 | fclose(fp); 350 | } else { // input format is LAS 351 | #ifdef USE_LIBLAS_17 352 | LASReaderH lr = LASReader_Create(inputName); 353 | if (!lr) { 354 | LASError_Print("Could not open file to read."); 355 | return -1; 356 | } 357 | 358 | LASPointH lp; 359 | while ((lp = LASReader_GetNextPoint(lr))) { 360 | data_x = LASPoint_GetX(lp); 361 | data_y = LASPoint_GetY(lp); 362 | data_z = LASPoint_GetZ(lp); 363 | 364 | data_x -= min_x; 365 | data_y -= min_y; 366 | 367 | if ((rc = interp->update(data_x, data_y, data_z)) < 0) { 368 | cout << "interp->update() error while processing " << endl; 369 | return -1; 370 | } 371 | } 372 | 373 | LASReader_Destroy(lr); 374 | #else 375 | // instantiate a reader for the LAS file 376 | std::ifstream ifs; 377 | ifs.open(inputName, std::ios::in | std::ios::binary); 378 | 379 | liblas::LASReader reader(ifs); 380 | 381 | // process every point in the LAS file, and generate DEM 382 | while (reader.ReadNextPoint()) { 383 | liblas::LASPoint const& p = reader.GetPoint(); 384 | 385 | data_x = p.GetX(); 386 | data_y = p.GetY(); 387 | data_z = p.GetZ(); 388 | 389 | data_x -= min_x; 390 | data_y -= min_y; 391 | 392 | //if((rc = interp->update(arrX[i], arrY[i], arrZ[i])) < 0) 393 | if((rc = interp->update(data_x, data_y, data_z)) < 0) 394 | { 395 | cout << "interp->update() error while processing " << endl; 396 | return -1; 397 | } 398 | } 399 | 400 | ifs.close(); 401 | #endif 402 | } 403 | 404 | if((rc = interp->finish(outputName, outputFormat, outputType)) < 0) 405 | { 406 | cout << "interp->finish() error" << endl; 407 | return -1; 408 | } 409 | 410 | cout << "Interpolation::interpolation() done successfully" << endl; 411 | 412 | 413 | return 0; 414 | } 415 | 416 | void Interpolation::setRadius(double r) 417 | { 418 | radius_sqr = r * r; 419 | } 420 | 421 | unsigned int Interpolation::getDataCount() 422 | { 423 | return data_count; 424 | } 425 | 426 | unsigned int Interpolation::getGridSizeX() 427 | { 428 | return GRID_SIZE_X; 429 | } 430 | 431 | unsigned int Interpolation::getGridSizeY() 432 | { 433 | return GRID_SIZE_Y; 434 | } 435 | 436 | -------------------------------------------------------------------------------- /InCoreInterp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #include "InCoreInterp.h" 48 | 49 | #include 50 | #include 51 | #include "Interpolation.h" 52 | #include "Global.h" 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | InCoreInterp::InCoreInterp(double dist_x, double dist_y, 59 | int size_x, int size_y, 60 | double r_sqr, 61 | double _min_x, double _max_x, 62 | double _min_y, double _max_y, 63 | int _window_size) 64 | { 65 | GRID_DIST_X = dist_x; 66 | GRID_DIST_Y = dist_y; 67 | 68 | GRID_SIZE_X = size_x; 69 | GRID_SIZE_Y = size_y; 70 | 71 | radius_sqr = r_sqr; 72 | 73 | min_x = _min_x; 74 | max_x = _max_x; 75 | min_y = _min_y; 76 | max_y = _max_y; 77 | 78 | window_size = _window_size; 79 | 80 | cout << "InCoreInterp created successfully" << endl; 81 | } 82 | 83 | InCoreInterp::~InCoreInterp() 84 | { 85 | int i; 86 | for(i = 0; i < GRID_SIZE_X; i++) 87 | delete interp[i]; 88 | delete interp; 89 | } 90 | 91 | int InCoreInterp::init() 92 | { 93 | int i, j; 94 | 95 | interp = (GridPoint**)malloc(sizeof(GridPoint *) * GRID_SIZE_X); 96 | //interp = new GridPoint*[GRID_SIZE_X]; 97 | if(interp == NULL) 98 | { 99 | cout << "InCoreInterp::init() new allocate error" << endl; 100 | return -1; 101 | } 102 | 103 | for(i = 0; i < GRID_SIZE_X; i++) 104 | { 105 | interp[i] = (GridPoint *)malloc(sizeof(GridPoint) * GRID_SIZE_Y); 106 | //interp[i] = new GridPoint[GRID_SIZE_Y]; 107 | if(interp[i] == NULL) 108 | { 109 | cout << "InCoreInterp::init() new allocate error" << endl; 110 | return -1; 111 | } 112 | } 113 | 114 | for(i = 0; i < GRID_SIZE_X; i++) 115 | for(j = 0; j < GRID_SIZE_Y; j++) 116 | { 117 | interp[i][j].Zmin = DBL_MAX; 118 | interp[i][j].Zmax = -DBL_MAX; 119 | interp[i][j].Zmean = 0; 120 | interp[i][j].count = 0; 121 | interp[i][j].Zidw = 0; 122 | interp[i][j].sum = 0; 123 | interp[i][j].empty = 0; 124 | interp[i][j].filled = 0; 125 | } 126 | 127 | cout << "InCoreInterp::init() done" << endl; 128 | 129 | return 0; 130 | } 131 | 132 | int InCoreInterp::update(double data_x, double data_y, double data_z) 133 | { 134 | double x; 135 | double y; 136 | 137 | int lower_grid_x; 138 | int lower_grid_y; 139 | 140 | lower_grid_x = (int)floor((double)data_x/GRID_DIST_X); 141 | lower_grid_y = (int)floor((double)data_y/GRID_DIST_Y); 142 | 143 | if(lower_grid_x >= GRID_SIZE_X || lower_grid_y >= GRID_SIZE_Y) 144 | { 145 | cout << "larger at (" << lower_grid_x << "," << lower_grid_y << "): ("<< data_x << ", " << data_y << ")" << endl; 146 | return 0; 147 | } 148 | 149 | x = (data_x - (lower_grid_x) * GRID_DIST_X); 150 | y = (data_y - (lower_grid_y) * GRID_DIST_Y); 151 | 152 | 153 | update_first_quadrant(data_z, lower_grid_x+1, lower_grid_y+1, GRID_DIST_X - x, GRID_DIST_Y - y); 154 | update_second_quadrant(data_z, lower_grid_x, lower_grid_y+1, x, GRID_DIST_Y - y); 155 | update_third_quadrant(data_z, lower_grid_x, lower_grid_y, x, y); 156 | update_fourth_quadrant(data_z, lower_grid_x+1, lower_grid_y, GRID_DIST_X - x, y); 157 | 158 | return 0; 159 | } 160 | 161 | int InCoreInterp::finish(char *outputName, int outputFormat, unsigned int outputType) 162 | { 163 | int rc; 164 | int i,j; 165 | 166 | //struct tms tbuf; 167 | clock_t t0, t1; 168 | 169 | for(i = 0; i < GRID_SIZE_X; i++) 170 | for(j = 0; j < GRID_SIZE_Y; j++) 171 | { 172 | if(interp[i][j].Zmin == DBL_MAX){ 173 | // interp[i][j].Zmin = NAN; 174 | interp[i][j].Zmin = 0; 175 | } 176 | 177 | if(interp[i][j].Zmax == -DBL_MAX){ 178 | //interp[i][j].Zmax = NAN; 179 | interp[i][j].Zmax = 0; 180 | } 181 | 182 | if(interp[i][j].count != 0) { 183 | interp[i][j].Zmean /= interp[i][j].count; 184 | interp[i][j].empty = 1; 185 | } else{ 186 | //interp[i][j].Zmean = NAN; 187 | interp[i][j].Zmean = 0; 188 | } 189 | 190 | if(interp[i][j].sum != 0 && interp[i][j].sum != -1) 191 | interp[i][j].Zidw /= interp[i][j].sum; 192 | else if (interp[i][j].sum == -1){ 193 | // do nothing 194 | } else{ 195 | //interp[i][j].Zidw = NAN; 196 | interp[i][j].Zidw = 0; 197 | } 198 | } 199 | 200 | // Sriram's edit: Fill zeros using the window size parameter 201 | if (window_size != 0) { 202 | int window_dist = window_size / 2; 203 | for (int i = 0; i < GRID_SIZE_X; i++) 204 | for (int j = 0; j < GRID_SIZE_Y; j++) 205 | { 206 | if (interp[i][j].empty == 0) { 207 | double new_sum=0.0; 208 | for (int p = i - window_dist; p <= i + window_dist; p++) { 209 | for (int q = j - window_dist; q <= j + window_dist; q++) { 210 | if ((p >= 0) && (p < GRID_SIZE_X) && (q >=0) && (q < GRID_SIZE_Y)) { 211 | if ((p == i) && (q == j)) 212 | continue; 213 | 214 | if (interp[p][q].empty != 0) { 215 | double distance = max(fabs(p-i), fabs(q-j)); 216 | interp[i][j].Zmean += interp[p][q].Zmean/(pow(distance,Interpolation::WEIGHTER)); 217 | interp[i][j].Zidw += interp[p][q].Zidw/(pow(distance,Interpolation::WEIGHTER)); 218 | interp[i][j].Zmin += interp[p][q].Zmin/(pow(distance,Interpolation::WEIGHTER)); 219 | interp[i][j].Zmax += interp[p][q].Zmax/(pow(distance,Interpolation::WEIGHTER)); 220 | 221 | new_sum += 1/(pow(distance,Interpolation::WEIGHTER)); 222 | } 223 | } 224 | } 225 | } 226 | if (new_sum > 0) { 227 | interp[i][j].Zmean /= new_sum; 228 | interp[i][j].Zidw /= new_sum; 229 | interp[i][j].Zmin /= new_sum; 230 | interp[i][j].Zmax /= new_sum; 231 | interp[i][j].filled = 1; 232 | } 233 | } 234 | } 235 | } 236 | 237 | t0 = clock(); 238 | 239 | if((rc = outputFile(outputName, outputFormat, outputType)) < 0) 240 | { 241 | cout << "InCoreInterp::finish outputFile error" << endl; 242 | return -1; 243 | } 244 | 245 | t1 = clock(); 246 | //t1 = times(&tbuf); 247 | 248 | printf("Output Execution time: %10.2f\n", (double)(t1 - t0)/ CLOCKS_PER_SEC); 249 | 250 | 251 | return 0; 252 | } 253 | 254 | ////////////////////////////////////////////////////// 255 | // Private Methods 256 | ////////////////////////////////////////////////////// 257 | 258 | void InCoreInterp::update_first_quadrant(double data_z, int base_x, int base_y, double x, double y) 259 | { 260 | int i; 261 | int j; 262 | //double temp; 263 | 264 | //printf("radius: %f ", radius_sqrt); 265 | 266 | for(i = base_x; i < GRID_SIZE_X; i++) 267 | { 268 | for(j = base_y; j < GRID_SIZE_Y; j++) 269 | { 270 | /* 271 | temp = ( ((i - base_x)*GRID_DIST + x) * ((i - base_x)*GRID_DIST + x) + 272 | ((j - base_y)*GRID_DIST + y) * ((j - base_y)*GRID_DIST + y)) ; 273 | printf("%f ", temp); 274 | */ 275 | 276 | double distance = ((i - base_x)*GRID_DIST_X + x) * ((i - base_x)*GRID_DIST_X + x) + 277 | ((j - base_y)*GRID_DIST_Y + y) * ((j - base_y)*GRID_DIST_Y + y) ; 278 | 279 | if(distance <= radius_sqr) 280 | { 281 | //printf("(%d %d) ", i, j); 282 | //interp[i][j]++; 283 | 284 | // update GridPoint 285 | updateGridPoint(i, j, data_z, distance); 286 | 287 | } else if(j == base_y) { 288 | //printf("return "); 289 | return; 290 | } else { 291 | //printf("break "); 292 | break; 293 | } 294 | } 295 | } 296 | 297 | } 298 | 299 | 300 | void InCoreInterp::update_second_quadrant(double data_z, int base_x, int base_y, double x, double y) 301 | { 302 | int i; 303 | int j; 304 | 305 | for(i = base_x; i >= 0; i--) 306 | { 307 | for(j = base_y; j < GRID_SIZE_Y; j++) 308 | { 309 | double distance = ((base_x - i)*GRID_DIST_X + x) * ((base_x - i)*GRID_DIST_X + x) + 310 | ((j - base_y)*GRID_DIST_Y + y) * ((j - base_y)*GRID_DIST_Y + y); 311 | 312 | if(distance <= radius_sqr) 313 | { 314 | //printf("(%d %d) ", i, j); 315 | //interp[i][j]++; 316 | 317 | updateGridPoint(i, j, data_z, sqrt(distance)); 318 | 319 | } else if(j == base_y){ 320 | return; 321 | } else { 322 | break; 323 | } 324 | } 325 | } 326 | 327 | } 328 | 329 | 330 | void InCoreInterp::update_third_quadrant(double data_z, int base_x, int base_y, double x, double y) 331 | { 332 | int i; 333 | int j; 334 | 335 | for(i = base_x; i >= 0; i--) 336 | { 337 | for(j = base_y; j >= 0; j--) 338 | { 339 | double distance = ((base_x - i)*GRID_DIST_X + x) * ((base_x - i)*GRID_DIST_X + x) + 340 | ((base_y - j)*GRID_DIST_Y + y) * ((base_y - j)*GRID_DIST_Y + y); 341 | 342 | if(distance <= radius_sqr) 343 | { 344 | //if(j == 30) 345 | //printf("(%d %d)\n", i, j); 346 | //interp[i][j]++; 347 | updateGridPoint(i, j, data_z, sqrt(distance)); 348 | } else if(j == base_y){ 349 | return; 350 | } else { 351 | break; 352 | } 353 | } 354 | } 355 | } 356 | 357 | void InCoreInterp::update_fourth_quadrant(double data_z, int base_x, int base_y, double x, double y) 358 | { 359 | int i, j; 360 | 361 | for(i = base_x; i < GRID_SIZE_X; i++) 362 | { 363 | for(j = base_y; j >= 0; j--) 364 | { 365 | double distance = ((i - base_x)*GRID_DIST_X + x) * ((i - base_x)*GRID_DIST_X + x) + 366 | ((base_y - j)*GRID_DIST_Y + y) * ((base_y - j)*GRID_DIST_Y + y); 367 | 368 | if(distance <= radius_sqr) 369 | { 370 | //printf("(%d %d) ", i, j); 371 | //interp[i][j]++; 372 | updateGridPoint(i, j, data_z, sqrt(distance)); 373 | } else if (j == base_y) { 374 | return ; 375 | } else { 376 | break; 377 | } 378 | } 379 | } 380 | } 381 | 382 | void InCoreInterp::updateGridPoint(int x, int y, double data_z, double distance) 383 | { 384 | #if 1 385 | //improved sanity-check is called on every update of the grid. 386 | if(x >= GRID_SIZE_X || y >= GRID_SIZE_Y) 387 | { 388 | printf("skipping grid point update for %d, %d:\tz: %f, dist: %f\n", x,y,data_z, distance); 389 | return; 390 | } 391 | #endif 392 | 393 | if(interp[x][y].Zmin > data_z) 394 | interp[x][y].Zmin = data_z; 395 | if(interp[x][y].Zmax < data_z) 396 | interp[x][y].Zmax = data_z; 397 | 398 | interp[x][y].Zmean += data_z; 399 | interp[x][y].count++; 400 | 401 | double dist = pow(distance, Interpolation::WEIGHTER); 402 | 403 | if(interp[x][y].sum != -1) { 404 | if(dist != 0) { 405 | interp[x][y].Zidw += data_z/dist; 406 | interp[x][y].sum += 1/dist; 407 | } else { 408 | interp[x][y].Zidw = data_z; 409 | interp[x][y].sum = -1; 410 | } 411 | } else { 412 | // do nothing 413 | } 414 | } 415 | 416 | void InCoreInterp::printArray() 417 | { 418 | int i, j; 419 | 420 | for(i = 0; i < GRID_SIZE_X; i++) 421 | { 422 | for(j = 1; j < GRID_SIZE_Y; j++) 423 | { 424 | cout << interp[i][j].Zmin << ", " << interp[i][j].Zmax << ", "; 425 | cout << interp[i][j].Zmean << ", " << interp[i][j].Zidw << endl; 426 | //printf("%.20f ", interp[i][j].Zmax); 427 | } 428 | //printf("\n"); 429 | } 430 | cout << endl; 431 | } 432 | 433 | int InCoreInterp::outputFile(char *outputName, int outputFormat, unsigned int outputType) 434 | { 435 | int i,j,k; 436 | 437 | FILE **arcFiles; 438 | char arcFileName[1024]; 439 | 440 | FILE **gridFiles; 441 | char gridFileName[1024]; 442 | 443 | char *ext[5] = {".min", ".max", ".mean", ".idw", ".den"}; 444 | unsigned int type[5] = {OUTPUT_TYPE_MIN, OUTPUT_TYPE_MAX, OUTPUT_TYPE_MEAN, OUTPUT_TYPE_IDW, OUTPUT_TYPE_DEN}; 445 | int numTypes = 5; 446 | 447 | 448 | 449 | // open ArcGIS files 450 | if(outputFormat == OUTPUT_FORMAT_ARC_ASCII || outputFormat == OUTPUT_FORMAT_ALL) 451 | { 452 | if((arcFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) 453 | { 454 | cout << "Arc File open error: " << endl; 455 | return -1; 456 | } 457 | 458 | for(i = 0; i < numTypes; i++) 459 | { 460 | if(outputType & type[i]) 461 | { 462 | strncpy(arcFileName, outputName, sizeof(arcFileName)); 463 | strncat(arcFileName, ext[i], strlen(ext[i])); 464 | strncat(arcFileName, ".asc", strlen(".asc")); 465 | 466 | if((arcFiles[i] = fopen64(arcFileName, "w+")) == NULL) 467 | { 468 | cout << "File open error: " << arcFileName << endl; 469 | return -1; 470 | } 471 | }else{ 472 | arcFiles[i] = NULL; 473 | } 474 | } 475 | } else { 476 | arcFiles = NULL; 477 | } 478 | 479 | // open Grid ASCII files 480 | if(outputFormat == OUTPUT_FORMAT_GRID_ASCII || outputFormat == OUTPUT_FORMAT_ALL) 481 | { 482 | if((gridFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) 483 | { 484 | cout << "File array allocation error" << endl; 485 | return -1; 486 | } 487 | 488 | for(i = 0; i < numTypes; i++) 489 | { 490 | if(outputType & type[i]) 491 | { 492 | strncpy(gridFileName, outputName, sizeof(arcFileName)); 493 | strncat(gridFileName, ext[i], strlen(ext[i])); 494 | strncat(gridFileName, ".grid", strlen(".grid")); 495 | 496 | if((gridFiles[i] = fopen64(gridFileName, "w+")) == NULL) 497 | { 498 | cout << "File open error: " << gridFileName << endl; 499 | return -1; 500 | } 501 | }else{ 502 | gridFiles[i] = NULL; 503 | } 504 | } 505 | } else { 506 | gridFiles = NULL; 507 | } 508 | 509 | // print ArcGIS headers 510 | if(arcFiles != NULL) 511 | { 512 | for(i = 0; i < numTypes; i++) 513 | { 514 | if(arcFiles[i] != NULL) 515 | { 516 | fprintf(arcFiles[i], "ncols %d\n", GRID_SIZE_X); 517 | fprintf(arcFiles[i], "nrows %d\n", GRID_SIZE_Y); 518 | fprintf(arcFiles[i], "xllcorner %f\n", min_x); 519 | fprintf(arcFiles[i], "yllcorner %f\n", min_y); 520 | fprintf(arcFiles[i], "cellsize %f\n", GRID_DIST_X); 521 | fprintf(arcFiles[i], "NODATA_value -9999\n"); 522 | } 523 | } 524 | } 525 | 526 | // print Grid headers 527 | if(gridFiles != NULL) 528 | { 529 | for(i = 0; i < numTypes; i++) 530 | { 531 | if(gridFiles[i] != NULL) 532 | { 533 | fprintf(gridFiles[i], "north: %f\n", max_y); 534 | fprintf(gridFiles[i], "south: %f\n", min_y); 535 | fprintf(gridFiles[i], "east: %f\n", max_x); 536 | fprintf(gridFiles[i], "west: %f\n", min_x); 537 | fprintf(gridFiles[i], "rows: %d\n", GRID_SIZE_Y); 538 | fprintf(gridFiles[i], "cols: %d\n", GRID_SIZE_X); 539 | } 540 | } 541 | } 542 | 543 | // print data 544 | for(i = GRID_SIZE_Y - 1; i >= 0; i--) 545 | { 546 | for(j = 0; j < GRID_SIZE_X; j++) 547 | { 548 | if(arcFiles != NULL) 549 | { 550 | // Zmin 551 | if(arcFiles[0] != NULL) 552 | { 553 | if(interp[j][i].empty == 0 && 554 | interp[j][i].filled == 0) 555 | fprintf(arcFiles[0], "-9999 "); 556 | else 557 | fprintf(arcFiles[0], "%f ", interp[j][i].Zmin); 558 | } 559 | 560 | // Zmax 561 | if(arcFiles[1] != NULL) 562 | { 563 | if(interp[j][i].empty == 0 && 564 | interp[j][i].filled == 0) 565 | fprintf(arcFiles[1], "-9999 "); 566 | else 567 | fprintf(arcFiles[1], "%f ", interp[j][i].Zmax); 568 | } 569 | 570 | // Zmean 571 | if(arcFiles[2] != NULL) 572 | { 573 | if(interp[j][i].empty == 0 && 574 | interp[j][i].filled == 0) 575 | fprintf(arcFiles[2], "-9999 "); 576 | else 577 | fprintf(arcFiles[2], "%f ", interp[j][i].Zmean); 578 | } 579 | 580 | // Zidw 581 | if(arcFiles[3] != NULL) 582 | { 583 | if(interp[j][i].empty == 0 && 584 | interp[j][i].filled == 0) 585 | fprintf(arcFiles[3], "-9999 "); 586 | else 587 | fprintf(arcFiles[3], "%f ", interp[j][i].Zidw); 588 | } 589 | 590 | // count 591 | if(arcFiles[4] != NULL) 592 | { 593 | if(interp[j][i].empty == 0 && 594 | interp[j][i].filled == 0) 595 | fprintf(arcFiles[4], "-9999 "); 596 | else 597 | fprintf(arcFiles[4], "%d ", interp[j][i].count); 598 | } 599 | } 600 | 601 | if(gridFiles != NULL) 602 | { 603 | // Zmin 604 | if(gridFiles[0] != NULL) 605 | { 606 | if(interp[j][i].empty == 0 && 607 | interp[j][i].filled == 0) 608 | fprintf(gridFiles[0], "-9999 "); 609 | else 610 | fprintf(gridFiles[0], "%f ", interp[j][i].Zmin); 611 | } 612 | 613 | // Zmax 614 | if(gridFiles[1] != NULL) 615 | { 616 | if(interp[j][i].empty == 0 && 617 | interp[j][i].filled == 0) 618 | fprintf(gridFiles[1], "-9999 "); 619 | else 620 | fprintf(gridFiles[1], "%f ", interp[j][i].Zmax); 621 | } 622 | 623 | // Zmean 624 | if(gridFiles[2] != NULL) 625 | { 626 | if(interp[j][i].empty == 0 && 627 | interp[j][i].filled == 0) 628 | fprintf(gridFiles[2], "-9999 "); 629 | else 630 | fprintf(gridFiles[2], "%f ", interp[j][i].Zmean); 631 | } 632 | 633 | // Zidw 634 | if(gridFiles[3] != NULL) 635 | { 636 | if(interp[j][i].empty == 0 && 637 | interp[j][i].filled == 0) 638 | fprintf(gridFiles[3], "-9999 "); 639 | else 640 | fprintf(gridFiles[3], "%f ", interp[j][i].Zidw); 641 | } 642 | 643 | // count 644 | if(gridFiles[4] != NULL) 645 | { 646 | if(interp[j][i].empty == 0 && 647 | interp[j][i].filled == 0) 648 | fprintf(gridFiles[4], "-9999 "); 649 | else 650 | fprintf(gridFiles[4], "%d ", interp[j][i].count); 651 | } 652 | } 653 | } 654 | if(arcFiles != NULL) 655 | for(k = 0; k < numTypes; k++) 656 | { 657 | if(arcFiles[k] != NULL) 658 | fprintf(arcFiles[k], "\n"); 659 | } 660 | if(gridFiles != NULL) 661 | for(k = 0; k < numTypes; k++) 662 | { 663 | if(gridFiles[k] != NULL) 664 | fprintf(gridFiles[k], "\n"); 665 | } 666 | } 667 | 668 | // close files 669 | if(gridFiles != NULL) 670 | { 671 | for(i = 0; i < numTypes; i++) 672 | { 673 | if(gridFiles[i] != NULL) 674 | fclose(gridFiles[i]); 675 | } 676 | } 677 | 678 | if(arcFiles != NULL) 679 | { 680 | for(i = 0; i < numTypes; i++) 681 | { 682 | if(arcFiles[i] != NULL) 683 | fclose(arcFiles[i]); 684 | } 685 | } 686 | 687 | 688 | return 0; 689 | } 690 | 691 | -------------------------------------------------------------------------------- /OutCoreInterp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | COPYRIGHT AND LICENSE 4 | 5 | Copyright (c) 2011 The Regents of the University of California. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or 9 | without modification, are permitted provided that the following 10 | conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials provided 18 | with the distribution. 19 | 20 | 3. All advertising materials mentioning features or use of this 21 | software must display the following acknowledgement: This product 22 | includes software developed by the San Diego Supercomputer Center. 23 | 24 | 4. Neither the names of the Centers nor the names of the contributors 25 | may be used to endorse or promote products derived from this 26 | software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 31 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 32 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | POSSIBILITY OF SUCH DAMAGE. 40 | * 41 | * 42 | * Based on the notes by Prof. Ramon Arrowsmith(ramon.arrowsmith@asu.edu) 43 | * Authors: Han S Kim (hskim@cs.ucsd.edu), Sriram Krishnan (sriram@sdsc.edu) 44 | * 45 | */ 46 | 47 | #include "OutCoreInterp.h" 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include "Interpolation.h" 55 | #include "Global.h" 56 | #include 57 | #include 58 | 59 | OutCoreInterp::OutCoreInterp(double dist_x, double dist_y, 60 | int size_x, int size_y, 61 | double r_sqr, 62 | double _min_x, double _max_x, 63 | double _min_y, double _max_y, 64 | int _window_size) 65 | { 66 | int i; 67 | 68 | GRID_DIST_X = dist_x; 69 | GRID_DIST_Y = dist_y; 70 | 71 | GRID_SIZE_X = size_x; 72 | GRID_SIZE_Y = size_y; 73 | 74 | radius_sqr = r_sqr; 75 | 76 | min_x = _min_x; 77 | max_x = _max_x; 78 | min_y = _min_y; 79 | max_y = _max_y; 80 | 81 | window_size = _window_size; 82 | 83 | overlapSize = (int)ceil(sqrt(radius_sqr)/GRID_DIST_Y); 84 | int window_dist = window_size / 2; 85 | if (window_dist > overlapSize) { 86 | overlapSize = window_dist; 87 | } 88 | 89 | // how many pieces will there be? 90 | // numFiles = (GRID_SIZE_X*GRID_SIZE_Y + (2 * overlapSize + 1) * GRID_SIZE_X * numFiles) / MEM_LIMIT; 91 | // (2 * overlapSize + 1) means, each component has one more row to handle the points in-between two components. 92 | numFiles = (int)ceil((double)GRID_SIZE_X * GRID_SIZE_Y / (Interpolation::MEM_LIMIT - (2 * overlapSize + 1) * GRID_SIZE_X)); 93 | cout << "numFiles " << numFiles << endl; 94 | 95 | if(numFiles == 0) 96 | cout << "The number of files is 0!" << endl; 97 | 98 | // row-wise decomposition 99 | 100 | local_grid_size_x = GRID_SIZE_X; 101 | local_grid_size_y = (int)ceil((double)GRID_SIZE_Y/numFiles); 102 | 103 | 104 | // define overlap.. a funtion of (radius_sqr) 105 | // overlap size: sqrt(radius_sqr)/GRID_DIST_Y; 106 | 107 | // construct a map indicating which file corresponds which area 108 | if((gridMap = new GridMap*[numFiles]) == NULL) 109 | cout << "OutCoreInterp::OutCoreInterp() GridMap[] allocation error" << endl; 110 | 111 | for(i = 0; i < numFiles; i++) 112 | { 113 | int lower_bound = i * local_grid_size_y; 114 | int upper_bound = (i+1) * local_grid_size_y - 1; 115 | 116 | if(upper_bound >= GRID_SIZE_Y) 117 | upper_bound = GRID_SIZE_Y - 1; 118 | 119 | int overlap_lower_bound = lower_bound - overlapSize; 120 | if(overlap_lower_bound < 0) 121 | overlap_lower_bound = 0; 122 | 123 | int overlap_upper_bound = upper_bound + overlapSize + 1; 124 | if(overlap_upper_bound >= GRID_SIZE_Y) 125 | overlap_upper_bound = GRID_SIZE_Y - 1; 126 | 127 | char fname[1024]; 128 | 129 | struct timeval tp; 130 | gettimeofday(&tp, NULL); 131 | 132 | snprintf(fname, sizeof(fname), "data_%d_%ld", i, tp.tv_usec); 133 | 134 | gridMap[i] = new GridMap(i, 135 | GRID_SIZE_X, 136 | lower_bound, 137 | upper_bound, 138 | overlap_lower_bound, 139 | overlap_upper_bound, 140 | false, 141 | fname); 142 | if(gridMap[i] == NULL) 143 | cout << "OutCoreInterp::OutCoreInterp() GridMap alloc error" << endl; 144 | 145 | cout << "[" << lower_bound << "," << upper_bound << "]" << endl; 146 | cout << "[" << overlap_lower_bound << "," << overlap_upper_bound << "]" << endl; 147 | } 148 | 149 | // initializing queues 150 | qlist = new list [numFiles]; 151 | if(qlist == NULL) 152 | cout << "OutCoreInterp::OutCoreInterp() qlist alloc error" << endl; 153 | 154 | openFile = -1; 155 | 156 | //cout << overlapSize << endl; 157 | //cout << "data size: " << (size_x * size_y) << " numFiles: " << numFiles << " local_grid_size_y: " << local_grid_size_y << " overlap: " << overlapSize << endl; 158 | //cout << fname << endl; 159 | //cout << "GridMap is created: " << i << endl; 160 | } 161 | 162 | OutCoreInterp::~OutCoreInterp() 163 | { 164 | /* 165 | if(qlist != NULL) 166 | delete qlist; 167 | */ 168 | 169 | for(int i = 0; i < numFiles; i++) 170 | { 171 | //cout << "gridMap " << i << " deleted" << endl; 172 | if(gridMap[i] != NULL) 173 | delete gridMap[i]; 174 | } 175 | if(gridMap != NULL) 176 | delete gridMap; 177 | } 178 | 179 | int OutCoreInterp::init() 180 | { 181 | // open up a memory mapped file 182 | openFile = 0; 183 | gridMap[openFile]->getGridFile()->map(); 184 | 185 | return 0; 186 | } 187 | 188 | int OutCoreInterp::update(double data_x, double data_y, double data_z) 189 | { 190 | 191 | int fileNum; 192 | 193 | //fileNum = upper_grid_y / local_grid_size_y; 194 | if((fileNum = findFileNum(data_y)) < 0) 195 | { 196 | cout << "OutCoreInterp::update() findFileNum() error!" << endl; 197 | cout << "data_x: " << data_x << " data_y: " << data_y << " grid_y: " << (int)(data_y/GRID_DIST_Y) << " fileNum: " << fileNum << " open file: " << openFile << endl; 198 | return -1; 199 | } 200 | 201 | if(openFile == fileNum) 202 | { 203 | // write into memory; 204 | updateInterpArray(fileNum, data_x, data_y, data_z); 205 | 206 | }else{ 207 | UpdateInfo ui(data_x, data_y, data_z); 208 | qlist[fileNum].push_back(ui); 209 | 210 | if(qlist[fileNum].size() == QUEUE_LIMIT) 211 | { 212 | //cout << "erase" << endl; 213 | if(openFile != -1) 214 | { 215 | // if we use mmap and write directly into disk, no need this step. 216 | // munmap would be enough for this step.. 217 | 218 | // write back to disk 219 | gridMap[openFile]->getGridFile()->unmap(); 220 | openFile = -1; 221 | } 222 | // upload from disk to memory 223 | gridMap[fileNum]->getGridFile()->map(); 224 | openFile = fileNum; 225 | 226 | // pop every update information 227 | list::const_iterator iter; 228 | 229 | for(iter = qlist[openFile].begin(); iter!= qlist[openFile].end(); iter++){ 230 | updateInterpArray(openFile, (*iter).data_x, (*iter).data_y, (*iter).data_z); 231 | } 232 | // flush 233 | qlist[openFile].erase(qlist[openFile].begin(), qlist[openFile].end()); 234 | } 235 | } 236 | 237 | return 0; 238 | } 239 | 240 | int OutCoreInterp::finish(char *outputName, int outputFormat, unsigned int outputType) 241 | { 242 | int i, j; 243 | GridPoint *p; 244 | GridFile *gf; 245 | int len_y; 246 | int offset; 247 | 248 | //struct tms tbuf; 249 | clock_t t0, t1; 250 | 251 | 252 | /* 253 | // managing overlap. 254 | read adjacent blocks and store ghost cells and update the cells 255 | 256 | merging multiple files 257 | */ 258 | if(openFile != -1){ 259 | gridMap[openFile]->getGridFile()->unmap(); 260 | openFile = -1; 261 | } 262 | 263 | for(i = 0; i < numFiles; i++) 264 | { 265 | if(qlist[i].size() != 0) 266 | { 267 | if((gf = gridMap[i]->getGridFile()) == NULL) 268 | { 269 | cout << "OutCoreInterp::finish() getGridFile() NULL" << endl; 270 | return -1; 271 | } 272 | 273 | gf->map(); 274 | openFile = i; 275 | 276 | // flush UpdateInfo queue 277 | // pop every update information 278 | list::const_iterator iter; 279 | 280 | for(iter = qlist[i].begin(); iter!= qlist[i].end(); iter++){ 281 | updateInterpArray(i, (*iter).data_x, (*iter).data_y, (*iter).data_z); 282 | } 283 | qlist[i].erase(qlist[i].begin(), qlist[i].end()); 284 | 285 | gf->unmap(); 286 | openFile = -1; 287 | gf = NULL; 288 | } 289 | } 290 | 291 | for(i = 0; i < numFiles - 1; i++) 292 | { 293 | // read the upside overlap 294 | 295 | if((gf = gridMap[i]->getGridFile()) == NULL) 296 | { 297 | cout << "OutCoreInterp::finish() getGridFile() NULL" << endl; 298 | return -1; 299 | } 300 | 301 | if(gf->map() != -1) 302 | { 303 | openFile = i; 304 | // Sriram's edit to copy over DEM values to overlap also 305 | len_y = 2 * (gridMap[i]->getOverlapUpperBound() - gridMap[i]->getUpperBound() - 1); 306 | 307 | if((p = (GridPoint *)malloc(sizeof(GridPoint) * len_y * GRID_SIZE_X)) == NULL) 308 | { 309 | cout << "OutCoreInterp::finish() malloc error" << endl; 310 | return -1; 311 | } 312 | 313 | int start = (gridMap[i]->getOverlapUpperBound() - gridMap[i]->getOverlapLowerBound() - len_y) * GRID_SIZE_X; 314 | cout << "copy from " << start << " to " << (start + len_y * GRID_SIZE_X) << endl; 315 | 316 | memcpy(p, &(gf->interp[start]), sizeof(GridPoint) * len_y * (GRID_SIZE_X) ); 317 | 318 | gf->unmap(); 319 | gf = NULL; 320 | openFile = -1; 321 | 322 | } else { 323 | cout << "OutCoreInterp::finish() gf->map() error" << endl; 324 | return -1; 325 | } 326 | // update (i+1)th component 327 | if((gf = gridMap[i+1]->getGridFile()) == NULL) 328 | { 329 | cout << "OutCoreInterp::finish() getGridFile() NULL" << endl; 330 | return -1; 331 | } 332 | 333 | if(gf->map() != -1) 334 | { 335 | offset = 0; 336 | openFile = i - 1; 337 | 338 | for(j = 0; j < len_y * GRID_SIZE_X; j++) 339 | { 340 | if(gf->interp[j + offset].Zmin > p[j].Zmin) 341 | gf->interp[j + offset].Zmin = p[j].Zmin; 342 | 343 | if(gf->interp[j + offset].Zmax < p[j].Zmax) 344 | gf->interp[j + offset].Zmax = p[j].Zmax; 345 | 346 | gf->interp[j + offset].Zmean += p[j].Zmean; 347 | gf->interp[j + offset].count += p[j].count; 348 | 349 | if (p[j].sum != -1) { 350 | gf->interp[j + offset].Zidw += p[j].Zidw; 351 | gf->interp[j + offset].sum += p[j].sum; 352 | } else { 353 | gf->interp[j + offset].Zidw = p[j].Zidw; 354 | gf->interp[j + offset].sum = p[j].sum; 355 | } 356 | } 357 | 358 | if(p != NULL){ 359 | free(p); 360 | p = NULL; 361 | } 362 | 363 | gf->unmap(); 364 | gf = NULL; 365 | openFile = -1; 366 | 367 | } else { 368 | cout << "OutCoreInterp::finish() gf->map() error" << endl; 369 | return -1; 370 | } 371 | } 372 | 373 | for(i = numFiles -1; i > 0; i--) 374 | { 375 | // read the downside overlap 376 | 377 | if((gf = gridMap[i]->getGridFile()) == NULL) 378 | { 379 | cout << "GridFile is NULL" << endl; 380 | return -1; 381 | } 382 | 383 | if(gf->map() != -1) 384 | { 385 | openFile = i; 386 | len_y = 2 * (gridMap[i]->getLowerBound() - gridMap[i]->getOverlapLowerBound()); 387 | 388 | if((p = (GridPoint *)malloc(sizeof(GridPoint) * len_y * GRID_SIZE_X)) == NULL) 389 | { 390 | cout << "OutCoreInterp::finish() malloc error" << endl; 391 | return -1; 392 | } 393 | 394 | memcpy(p, &(gf->interp[0]), len_y * sizeof(GridPoint) * GRID_SIZE_X); 395 | 396 | //finalize(); 397 | 398 | gf->unmap(); 399 | gf = NULL; 400 | openFile = -1; 401 | } else { 402 | cout << "OutCoreInterp::finish gf->map() error" << endl; 403 | return -1; 404 | } 405 | // update (i-1)th component 406 | if((gf = gridMap[i-1]->getGridFile()) == NULL) 407 | { 408 | cout << "GridFile is NULL" << endl; 409 | return -1; 410 | } 411 | 412 | if(gf->map() != -1) 413 | { 414 | offset = (gridMap[i-1]->getOverlapUpperBound() - gridMap[i-1]->getOverlapLowerBound() - len_y) * GRID_SIZE_X; 415 | openFile = i - 1; 416 | 417 | for(j = 0; j < len_y * GRID_SIZE_X; j++) 418 | { 419 | // Sriram - the overlap already contains the correct values 420 | gf->interp[j + offset].Zmin = p[j].Zmin; 421 | gf->interp[j + offset].Zmax = p[j].Zmax; 422 | gf->interp[j + offset].Zmean = p[j].Zmean; 423 | gf->interp[j + offset].count = p[j].count; 424 | gf->interp[j + offset].Zidw = p[j].Zidw; 425 | gf->interp[j + offset].sum = p[j].sum; 426 | } 427 | 428 | //if(i - 1 == 0) 429 | //finalize(); 430 | 431 | if(p != NULL){ 432 | free(p); 433 | p = NULL; 434 | } 435 | 436 | gf->unmap(); 437 | gf = NULL; 438 | openFile = -1; 439 | } 440 | } 441 | 442 | for(i = 0; i < numFiles; i++) 443 | { 444 | gridMap[i]->getGridFile()->map(); 445 | openFile = i; 446 | finalize(); 447 | gridMap[i]->getGridFile()->unmap(); 448 | openFile = -1; 449 | } 450 | 451 | 452 | 453 | t0 = clock(); 454 | 455 | // merge pieces into one file 456 | if(outputFile(outputName, outputFormat, outputType) < 0) 457 | { 458 | cout << "OutCoreInterp::finish outputFile error" << endl; 459 | return -1; 460 | } 461 | 462 | t1 = clock(); 463 | printf("Output Execution time: %10.2f\n", (double)(t1 - t0)/CLOCKS_PER_SEC); 464 | 465 | return 0; 466 | } 467 | 468 | void OutCoreInterp::updateInterpArray(int fileNum, double data_x, double data_y, double data_z) 469 | { 470 | double x; 471 | double y; 472 | 473 | int lower_grid_x; 474 | int lower_grid_y; 475 | 476 | lower_grid_x = (int)floor((double)data_x/GRID_DIST_X); // global/local coordinate 477 | lower_grid_y = (int)floor((double)data_y/GRID_DIST_Y); // global coordinate 478 | 479 | x = data_x - lower_grid_x * GRID_DIST_X; 480 | y = data_y - lower_grid_y * GRID_DIST_Y; 481 | 482 | // if the opened file is not the 0th file, then you have to consider the offset of the grid of the file!!! 483 | lower_grid_y -= gridMap[fileNum]->getOverlapLowerBound(); // local coordinate 484 | 485 | update_first_quadrant(fileNum, data_z, lower_grid_x + 1, lower_grid_y + 1, GRID_DIST_X -x, GRID_DIST_Y - y); 486 | update_second_quadrant(fileNum, data_z, lower_grid_x, lower_grid_y + 1, x, GRID_DIST_Y - y); 487 | update_third_quadrant(fileNum, data_z, lower_grid_x, lower_grid_y, x, y); 488 | update_fourth_quadrant(fileNum, data_z, lower_grid_x + 1, lower_grid_y, GRID_DIST_X - x, y); 489 | } 490 | 491 | 492 | void OutCoreInterp::update_first_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y) 493 | { 494 | // base_x, base_y: local coordinates 495 | 496 | int i; 497 | int j; 498 | int ub = gridMap[fileNum]->getOverlapUpperBound() - gridMap[fileNum]->getOverlapLowerBound(); 499 | 500 | for(i = base_x; i < GRID_SIZE_X; i++) 501 | { 502 | for(j = base_y; j < ub; j++) 503 | { 504 | // i, j, base_x, base_y: local coordinates 505 | double distance = ((i - base_x)*GRID_DIST_X + x) * ((i - base_x)*GRID_DIST_X + x) + 506 | ((j - base_y)*GRID_DIST_Y + y) * ((j - base_y)*GRID_DIST_Y + y) ; 507 | 508 | if(distance <= radius_sqr) 509 | { 510 | // update GridPoint 511 | updateGridPoint(fileNum, i, j, data_z, distance); 512 | 513 | } else if(j == base_y) { 514 | //printf("return "); 515 | return; 516 | } else { 517 | //printf("break "); 518 | break; 519 | } 520 | } 521 | } 522 | } 523 | 524 | 525 | void OutCoreInterp::update_second_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y) 526 | { 527 | int i; 528 | int j; 529 | int ub = gridMap[fileNum]->getOverlapUpperBound() - gridMap[fileNum]->getOverlapLowerBound(); 530 | //int ub = gridMap[fileNum]->getOverlapUpperBound(); 531 | 532 | for(i = base_x; i >= 0; i--) 533 | { 534 | for(j = base_y; j < ub; j++) 535 | { 536 | double distance = ((base_x - i)*GRID_DIST_X + x) * ((base_x - i)*GRID_DIST_X + x) + 537 | ((j - base_y)*GRID_DIST_Y + y) * ((j - base_y)*GRID_DIST_Y + y); 538 | 539 | if(distance <= radius_sqr) 540 | { 541 | //printf("(%d %d) ", i, j); 542 | //interp[i][j]++; 543 | 544 | updateGridPoint(fileNum, i, j, data_z, sqrt(distance)); 545 | 546 | } else if(j == base_y){ 547 | return; 548 | } else { 549 | break; 550 | } 551 | } 552 | } 553 | } 554 | 555 | void OutCoreInterp::update_third_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y) 556 | { 557 | int i; 558 | int j; 559 | //int lb = gridMap[fileNum]->getOverlapLowerBound(); 560 | 561 | for(i = base_x; i >= 0; i--) 562 | { 563 | //for(j = base_y; j >= lb; j--) 564 | for(j = base_y; j >= 0; j--) 565 | { 566 | double distance = ((base_x - i)*GRID_DIST_X + x) * ((base_x - i)*GRID_DIST_X + x) + 567 | ((base_y - j)*GRID_DIST_Y + y) * ((base_y - j)*GRID_DIST_Y + y); 568 | 569 | if(distance <= radius_sqr) 570 | { 571 | updateGridPoint(fileNum, i, j, data_z, sqrt(distance)); 572 | } else if(j == base_y){ 573 | return; 574 | } else { 575 | break; 576 | } 577 | } 578 | } 579 | } 580 | 581 | void OutCoreInterp::update_fourth_quadrant(int fileNum, double data_z, int base_x, int base_y, double x, double y) 582 | { 583 | int i, j; 584 | //int lb = gridMap[fileNum]->getOverlapLowerBound(); 585 | 586 | for(i = base_x; i < GRID_SIZE_X; i++) 587 | { 588 | //for(j = base_y; j >= lb; j--) 589 | for(j = base_y; j >= 0; j--) 590 | { 591 | double distance = ((i - base_x)*GRID_DIST_X + x) * ((i - base_x)*GRID_DIST_X + x) + 592 | ((base_y - j)*GRID_DIST_Y + y) * ((base_y - j)*GRID_DIST_Y + y); 593 | 594 | if(distance <= radius_sqr) 595 | { 596 | //printf("(%d %d) ", i, j); 597 | //interp[i][j]++; 598 | updateGridPoint(fileNum, i, j, data_z, sqrt(distance)); 599 | } else if (j == base_y) { 600 | return ; 601 | } else { 602 | break; 603 | } 604 | } 605 | } 606 | } 607 | 608 | void OutCoreInterp::updateGridPoint(int fileNum, int x, int y, double data_z, double distance) 609 | { 610 | unsigned int coord = y * local_grid_size_x + x; 611 | GridFile *gf = gridMap[fileNum]->getGridFile(); 612 | 613 | if(gf == NULL || gf->interp == NULL) 614 | { 615 | //cout << "OutCoreInterp::updateGridPoint() gridFile is NULL" << endl; 616 | return; 617 | } 618 | 619 | if(coord < gf->getMemSize() && coord >= 0) 620 | { 621 | if(gf->interp[coord].Zmin > data_z) 622 | gf->interp[coord].Zmin = data_z; 623 | if(gf->interp[coord].Zmax < data_z) 624 | gf->interp[coord].Zmax = data_z; 625 | 626 | gf->interp[coord].Zmean += data_z; 627 | gf->interp[coord].count++; 628 | 629 | double dist = pow(distance, Interpolation::WEIGHTER); 630 | if (gf->interp[coord].sum != -1) { 631 | if (dist != 0) { 632 | gf->interp[coord].Zidw += data_z/dist; 633 | gf->interp[coord].sum += 1/dist; 634 | } else { 635 | gf->interp[coord].Zidw = data_z; 636 | gf->interp[coord].sum = -1; 637 | } 638 | } else { 639 | // do nothing 640 | } 641 | } else { 642 | cout << "OutCoreInterp::updateGridPoint() Memory Access Violation!" << endl; 643 | } 644 | } 645 | 646 | int OutCoreInterp::outputFile(char *outputName, int outputFormat, unsigned int outputType) 647 | { 648 | int i, j, k, l; 649 | 650 | FILE **arcFiles; 651 | char arcFileName[1024]; 652 | 653 | FILE **gridFiles; 654 | char gridFileName[1024]; 655 | 656 | char *ext[5] = {".min", ".max", ".mean", ".idw", ".den"}; 657 | unsigned int type[5] = {OUTPUT_TYPE_MIN, OUTPUT_TYPE_MAX, OUTPUT_TYPE_MEAN, OUTPUT_TYPE_IDW, OUTPUT_TYPE_DEN}; 658 | int numTypes = 5; 659 | 660 | 661 | // open ArcGIS files 662 | if(outputFormat == OUTPUT_FORMAT_ARC_ASCII || outputFormat == OUTPUT_FORMAT_ALL) 663 | { 664 | if((arcFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) 665 | { 666 | cout << "Arc File open error: " << endl; 667 | return -1; 668 | } 669 | 670 | for(i = 0; i < numTypes; i++) 671 | { 672 | if(outputType & type[i]) 673 | { 674 | strncpy(arcFileName, outputName, sizeof(arcFileName)); 675 | strncat(arcFileName, ext[i], strlen(ext[i])); 676 | strncat(arcFileName, ".asc", strlen(".asc")); 677 | 678 | if((arcFiles[i] = fopen64(arcFileName, "w+")) == NULL) 679 | { 680 | cout << "File open error: " << arcFileName << endl; 681 | return -1; 682 | } 683 | }else{ 684 | arcFiles[i] = NULL; 685 | } 686 | } 687 | } else { 688 | arcFiles = NULL; 689 | } 690 | 691 | // open Grid ASCII files 692 | if(outputFormat == OUTPUT_FORMAT_GRID_ASCII || outputFormat == OUTPUT_FORMAT_ALL) 693 | { 694 | if((gridFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) 695 | { 696 | cout << "File array allocation error" << endl; 697 | return -1; 698 | } 699 | 700 | for(i = 0; i < numTypes; i++) 701 | { 702 | if(outputType & type[i]) 703 | { 704 | strncpy(gridFileName, outputName, sizeof(arcFileName)); 705 | strncat(gridFileName, ext[i], strlen(ext[i])); 706 | strncat(gridFileName, ".grid", strlen(".grid")); 707 | 708 | if((gridFiles[i] = fopen64(gridFileName, "w+")) == NULL) 709 | { 710 | cout << "File open error: " << gridFileName << endl; 711 | return -1; 712 | } 713 | }else{ 714 | gridFiles[i] = NULL; 715 | } 716 | } 717 | } else { 718 | gridFiles = NULL; 719 | } 720 | 721 | // print ArcGIS headers 722 | if(arcFiles != NULL) 723 | { 724 | for(i = 0; i < numTypes; i++) 725 | { 726 | if(arcFiles[i] != NULL) 727 | { 728 | fprintf(arcFiles[i], "ncols %d\n", GRID_SIZE_X); 729 | fprintf(arcFiles[i], "nrows %d\n", GRID_SIZE_Y); 730 | fprintf(arcFiles[i], "xllcorner %f\n", min_x); 731 | fprintf(arcFiles[i], "yllcorner %f\n", min_y); 732 | fprintf(arcFiles[i], "cellsize %f\n", GRID_DIST_X); 733 | fprintf(arcFiles[i], "NODATA_value -9999\n"); 734 | } 735 | } 736 | } 737 | 738 | // print Grid headers 739 | if(gridFiles != NULL) 740 | { 741 | for(i = 0; i < numTypes; i++) 742 | { 743 | if(gridFiles[i] != NULL) 744 | { 745 | fprintf(gridFiles[i], "north: %f\n", max_y); 746 | fprintf(gridFiles[i], "south: %f\n", min_y); 747 | fprintf(gridFiles[i], "east: %f\n", max_x); 748 | fprintf(gridFiles[i], "west: %f\n", min_x); 749 | fprintf(gridFiles[i], "rows: %d\n", GRID_SIZE_Y); 750 | fprintf(gridFiles[i], "cols: %d\n", GRID_SIZE_X); 751 | } 752 | } 753 | } 754 | 755 | 756 | for(i = numFiles -1; i >= 0; i--) 757 | { 758 | GridFile *gf = gridMap[i]->getGridFile(); 759 | gf->map(); 760 | 761 | int start = gridMap[i]->getLowerBound() - gridMap[i]->getOverlapLowerBound(); 762 | int end = gridMap[i]->getUpperBound() - gridMap[i]->getOverlapLowerBound() + 1; 763 | 764 | //int start = (gridMap[i]->getLowerBound() - gridMap[i]->getOverlapLowerBound()) * GRID_SIZE_X; 765 | //int end = (gridMap[i]->getUpperBound() - gridMap[i]->getOverlapLowerBound() + 1) * GRID_SIZE_X; 766 | 767 | cout << "Merging " << i << ": from " << (start) << " to " << (end) << endl; 768 | cout << " " << i << ": from " << (start/GRID_SIZE_X) << " to " << (end/GRID_SIZE_X) << endl; 769 | 770 | for(j = end - 1; j >= start; j--) 771 | { 772 | for(k = 0; k < GRID_SIZE_X; k++) 773 | { 774 | int index = j * GRID_SIZE_X + k; 775 | 776 | if(arcFiles != NULL) 777 | { 778 | // Zmin 779 | if(arcFiles[0] != NULL) 780 | { 781 | if(gf->interp[index].empty == 0 && 782 | gf->interp[index].filled == 0) 783 | //if(gf->interp[k][j].Zmin == 0) 784 | fprintf(arcFiles[0], "-9999 "); 785 | else 786 | //fprintf(arcFiles[0], "%f ", gf->interp[j][i].Zmin); 787 | fprintf(arcFiles[0], "%f ", gf->interp[index].Zmin); 788 | } 789 | 790 | // Zmax 791 | if(arcFiles[1] != NULL) 792 | { 793 | if(gf->interp[index].empty == 0 && 794 | gf->interp[index].filled == 0) 795 | fprintf(arcFiles[1], "-9999 "); 796 | else 797 | fprintf(arcFiles[1], "%f ", gf->interp[index].Zmax); 798 | } 799 | 800 | // Zmean 801 | if(arcFiles[2] != NULL) 802 | { 803 | if(gf->interp[index].empty == 0 && 804 | gf->interp[index].filled == 0) 805 | fprintf(arcFiles[2], "-9999 "); 806 | else 807 | fprintf(arcFiles[2], "%f ", gf->interp[index].Zmean); 808 | } 809 | 810 | // Zidw 811 | if(arcFiles[3] != NULL) 812 | { 813 | if(gf->interp[index].empty == 0 && 814 | gf->interp[index].filled == 0) 815 | fprintf(arcFiles[3], "-9999 "); 816 | else 817 | fprintf(arcFiles[3], "%f ", gf->interp[index].Zidw); 818 | } 819 | 820 | // count 821 | if(arcFiles[4] != NULL) 822 | { 823 | if(gf->interp[index].empty == 0 && 824 | gf->interp[index].filled == 0) 825 | fprintf(arcFiles[4], "-9999 "); 826 | else 827 | fprintf(arcFiles[4], "%d ", gf->interp[index].count); 828 | } 829 | } 830 | 831 | if(gridFiles != NULL) 832 | { 833 | // Zmin 834 | if(gridFiles[0] != NULL) 835 | { 836 | if(gf->interp[index].empty == 0 && 837 | gf->interp[index].filled == 0) 838 | fprintf(gridFiles[0], "-9999 "); 839 | else 840 | fprintf(gridFiles[0], "%f ", gf->interp[index].Zmin); 841 | } 842 | 843 | // Zmax 844 | if(gridFiles[1] != NULL) 845 | { 846 | if(gf->interp[index].empty == 0 && 847 | gf->interp[index].filled == 0) 848 | fprintf(gridFiles[1], "-9999 "); 849 | else 850 | fprintf(gridFiles[1], "%f ", gf->interp[index].Zmax); 851 | } 852 | 853 | // Zmean 854 | if(gridFiles[2] != NULL) 855 | { 856 | if(gf->interp[index].empty == 0 && 857 | gf->interp[index].filled == 0) 858 | fprintf(gridFiles[2], "-9999 "); 859 | else 860 | fprintf(gridFiles[2], "%f ", gf->interp[index].Zmean); 861 | } 862 | 863 | // Zidw 864 | if(gridFiles[3] != NULL) 865 | { 866 | if(gf->interp[index].empty == 0 && 867 | gf->interp[index].filled == 0) 868 | fprintf(gridFiles[3], "-9999 "); 869 | else 870 | fprintf(gridFiles[3], "%f ", gf->interp[index].Zidw); 871 | } 872 | 873 | // count 874 | if(gridFiles[4] != NULL) 875 | { 876 | if(gf->interp[index].empty == 0 && 877 | gf->interp[index].filled == 0) 878 | fprintf(gridFiles[4], "-9999 "); 879 | else 880 | fprintf(gridFiles[4], "%d ", gf->interp[index].count); 881 | } 882 | } 883 | } 884 | 885 | if(arcFiles != NULL) 886 | for(l = 0; l < numTypes; l++) 887 | { 888 | if(arcFiles[l] != NULL) 889 | fprintf(arcFiles[l], "\n"); 890 | } 891 | 892 | if(gridFiles != NULL) 893 | for(l = 0; l < numTypes; l++) 894 | { 895 | if(gridFiles[l] != NULL) 896 | fprintf(gridFiles[l], "\n"); 897 | } 898 | } 899 | 900 | gf->unmap(); 901 | } 902 | 903 | // close files 904 | if(gridFiles != NULL) 905 | { 906 | for(i = 0; i < numTypes; i++) 907 | { 908 | if(gridFiles[i] != NULL) 909 | fclose(gridFiles[i]); 910 | } 911 | } 912 | 913 | if(arcFiles != NULL) 914 | { 915 | for(i = 0; i < numTypes; i++) 916 | { 917 | if(arcFiles[i] != NULL) 918 | fclose(arcFiles[i]); 919 | } 920 | } 921 | 922 | return 0; 923 | } 924 | 925 | int OutCoreInterp::findFileNum(double data_y) 926 | { 927 | int i; 928 | 929 | for(i = 0; i < numFiles; i++) 930 | { 931 | if(data_y <= gridMap[i]->getUpperBound() * GRID_DIST_Y && 932 | data_y >= gridMap[i]->getLowerBound() * GRID_DIST_Y) 933 | return i; 934 | else if(i < numFiles - 1 && 935 | data_y > gridMap[i]->getUpperBound() * GRID_DIST_Y && 936 | data_y < gridMap[i+1]->getLowerBound() * GRID_DIST_Y) 937 | return i; 938 | else if(i == numFiles - 1 && 939 | data_y >= gridMap[i]->getUpperBound() * GRID_DIST_Y) 940 | { 941 | //cout << "here" << endl; 942 | return i; 943 | } 944 | } 945 | 946 | cout << "findFileNum() error" << endl; 947 | 948 | return -1; 949 | } 950 | 951 | void OutCoreInterp::finalize() 952 | { 953 | int i; 954 | int start; 955 | int end; 956 | int overlapEnd; 957 | GridFile *gf; 958 | 959 | if(openFile == -1) 960 | { 961 | cout << "OutCoreInterp::finalize() no open file" << endl; 962 | return; 963 | } 964 | 965 | start = (gridMap[openFile]->getLowerBound() - gridMap[openFile]->getOverlapLowerBound()) * GRID_SIZE_X; 966 | end = (gridMap[openFile]->getUpperBound() - gridMap[openFile]->getOverlapLowerBound() + 1) * GRID_SIZE_X; 967 | overlapEnd = (gridMap[openFile]->getOverlapUpperBound() - gridMap[openFile]->getOverlapLowerBound() + 1) * GRID_SIZE_X; 968 | gf = gridMap[openFile]->getGridFile(); 969 | 970 | cout << openFile << ": from " << (start) << " to " << (end) << endl; 971 | cout << openFile << ": from " << (start/GRID_SIZE_X) << " to " << (end/GRID_SIZE_X) << endl; 972 | 973 | for(i = 0; i < overlapEnd; i++) 974 | { 975 | if(gf->interp[i].Zmin == DBL_MAX) 976 | gf->interp[i].Zmin = 0; 977 | 978 | if(gf->interp[i].Zmax == -DBL_MAX) 979 | gf->interp[i].Zmax = 0; 980 | 981 | if(gf->interp[i].count != 0) { 982 | gf->interp[i].Zmean /= gf->interp[i].count ; 983 | gf->interp[i].empty = 1; 984 | } 985 | else 986 | gf->interp[i].Zmean = 0 ; 987 | 988 | if(gf->interp[i].sum != 0 && gf->interp[i].sum != -1) 989 | gf->interp[i].Zidw /= gf->interp[i].sum; 990 | else if (gf->interp[i].sum == -1) { 991 | // do nothing 992 | } else 993 | gf->interp[i].Zidw = 0; 994 | } 995 | 996 | // Sriram's edit: Fill zeros using the window size parameter 997 | if (window_size != 0) { 998 | int window_dist = window_size / 2; 999 | for (i = start; i < end; i++) 1000 | { 1001 | double new_sum=0.0; 1002 | if (gf->interp[i].empty == 0) { 1003 | for (int p = 0; p < window_size; p++) { 1004 | for (int q = 0; q < window_size; q++) { 1005 | // make sure that this is not an edge 1006 | int column = i - (i/local_grid_size_x)*local_grid_size_x; 1007 | if (((column + (p-window_dist)) < 0) || 1008 | (column + (p-window_dist) >= local_grid_size_x)) { 1009 | continue; 1010 | } 1011 | 1012 | int neighbor = (q-window_dist)*local_grid_size_x + (p-window_dist) + i; 1013 | if (neighbor == i) 1014 | continue; 1015 | 1016 | if ((neighbor >= 0) && (neighbor <= overlapEnd)) 1017 | if (gf->interp[neighbor].empty != 0) { 1018 | 1019 | double distance = max(fabs(p-window_dist), fabs(q-window_dist)); 1020 | gf->interp[i].Zmean += gf->interp[neighbor].Zmean/(pow(distance,Interpolation::WEIGHTER)); 1021 | gf->interp[i].Zidw += gf->interp[neighbor].Zidw/(pow(distance,Interpolation::WEIGHTER)); 1022 | gf->interp[i].Zmin += gf->interp[neighbor].Zmin/(pow(distance,Interpolation::WEIGHTER)); 1023 | gf->interp[i].Zmax += gf->interp[neighbor].Zmax/(pow(distance,Interpolation::WEIGHTER)); 1024 | new_sum += 1/(pow(distance,Interpolation::WEIGHTER)); 1025 | } 1026 | } 1027 | } 1028 | } 1029 | if (new_sum > 0) { 1030 | gf->interp[i].Zmean /= new_sum; 1031 | gf->interp[i].Zidw /= new_sum; 1032 | gf->interp[i].Zmin /= new_sum; 1033 | gf->interp[i].Zmax /= new_sum; 1034 | gf->interp[i].filled = 1; 1035 | } 1036 | } 1037 | } 1038 | } 1039 | 1040 | --------------------------------------------------------------------------------