diff options
author | Andrey Kislyuk <weaver@gentoo.org> | 2011-07-31 21:14:37 -0400 |
---|---|---|
committer | Andrey Kislyuk <weaver@gentoo.org> | 2011-07-31 21:14:37 -0400 |
commit | 0052a59b4635e455654932d725fc5b9a1aa5e057 (patch) | |
tree | becac7c25b6bc4af1dc2dcff5d65b9db5e38f5be /sci-libs/libspatialindex | |
parent | Make sure portage does not run gbrowse_metadb_config.pl otherwise sandbox vio... (diff) | |
download | sci-0052a59b4635e455654932d725fc5b9a1aa5e057.tar.gz sci-0052a59b4635e455654932d725fc5b9a1aa5e057.tar.bz2 sci-0052a59b4635e455654932d725fc5b9a1aa5e057.zip |
New package
Diffstat (limited to 'sci-libs/libspatialindex')
420 files changed, 80225 insertions, 0 deletions
diff --git a/sci-libs/libspatialindex/ChangeLog b/sci-libs/libspatialindex/ChangeLog new file mode 100644 index 000000000..3264865b2 --- /dev/null +++ b/sci-libs/libspatialindex/ChangeLog @@ -0,0 +1,10 @@ +# ChangeLog for sci-libs/libspatialindex +# Copyright 1999-2011 Gentoo Foundation; Distributed under the GPL v2 +# $Header: $ + +*libspatialindex-1.6.1 (01 Aug 2011) + + 01 Aug 2011; Andrey Kislyuk <weaver@gentoo.org> + +libspatialindex-1.6.1.ebuild, +metadata.xml: + New package, ebuild written by me + diff --git a/sci-libs/libspatialindex/Manifest b/sci-libs/libspatialindex/Manifest new file mode 100644 index 000000000..7b52d262f --- /dev/null +++ b/sci-libs/libspatialindex/Manifest @@ -0,0 +1,4 @@ +DIST spatialindex-src-1.6.1.tar.bz2 346819 RMD160 19d22e77305364d5e5d23ffe67fd5c9cf5e8e72c SHA1 b2044558c7af036b14f155f9228ad5eac7e20943 SHA256 42dc4149c04f7436632b3e15d5470fe80172e91f16a16665ffc5587b8c576fe4 +EBUILD libspatialindex-1.6.1.ebuild 548 RMD160 53bfd1216b24a257a64aa82c376d1dbb3d66363e SHA1 be114c019d5648e1151af4958b824f24b25191ac SHA256 7ee05e5efacb20dc89801742257eff2fc95aee68626e7bae09123b2b9569a876 +MISC ChangeLog 298 RMD160 8e48e08c243eb1c5f4768f86664f0eea987a126e SHA1 7d83c5f45daddd24415f82fbf73e551461ab696a SHA256 6128a205c3290c58521d69caa89cfe6a1a849876054bc11868c7142ef12f0786 +MISC metadata.xml 169 RMD160 e1db75ae5d177dffc400468c7d76a7e1fe41876d SHA1 0c953712f9b97d5ab3f95ae71997ffbc96c4007d SHA256 36837b011d26f0b83477c7a8632cb0099aedbcba5a3e45c61f20292e079f6180 diff --git a/sci-libs/libspatialindex/URL b/sci-libs/libspatialindex/URL new file mode 100644 index 000000000..0a95fd560 --- /dev/null +++ b/sci-libs/libspatialindex/URL @@ -0,0 +1 @@ +http://www2.research.att.com/~marioh/spatialindex/index.html diff --git a/sci-libs/libspatialindex/libspatialindex-1.6.1.ebuild b/sci-libs/libspatialindex/libspatialindex-1.6.1.ebuild new file mode 100644 index 000000000..9286f0250 --- /dev/null +++ b/sci-libs/libspatialindex/libspatialindex-1.6.1.ebuild @@ -0,0 +1,26 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header$ + +EAPI=4 + +MY_PN="spatialindex-src" +MY_P="${MY_PN}-${PV}" + +DESCRIPTION="General framework for developing spatial indices" +HOMEPAGE="http://trac.gispython.org/spatialindex/wiki" +SRC_URI="http://download.osgeo.org/libspatialindex/${MY_P}.tar.bz2" +LICENSE="GPL-2" + +KEYWORDS="~x86 ~amd64" +SLOT="0" +IUSE="" + +RDEPEND="" +DEPEND="${RDEPEND}" + +S="${WORKDIR}/${MY_P}" + +src_install() { + emake DESTDIR="${D}" install || die "einstall failed" +} diff --git a/sci-libs/libspatialindex/metadata.xml b/sci-libs/libspatialindex/metadata.xml new file mode 100644 index 000000000..3190fbf9c --- /dev/null +++ b/sci-libs/libspatialindex/metadata.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd"> +<pkgmetadata> + <herd>sci-geosciences</herd> +</pkgmetadata> diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/.svn/all-wcprops new file mode 100644 index 000000000..eb133b767 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/all-wcprops @@ -0,0 +1,113 @@ +K 25 +svn:wc:ra_dav:version-url +V 45 +/spatialindex/!svn/ver/203/spatialindex/trunk +END +HOWTORELEASE.txt +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/178/spatialindex/trunk/HOWTORELEASE.txt +END +spatialindex.sln +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/112/spatialindex/trunk/spatialindex.sln +END +mkinstalldirs +K 25 +svn:wc:ra_dav:version-url +V 58 +/spatialindex/!svn/ver/75/spatialindex/trunk/mkinstalldirs +END +makefile.vc +K 25 +svn:wc:ra_dav:version-url +V 57 +/spatialindex/!svn/ver/199/spatialindex/trunk/makefile.vc +END +AUTHORS +K 25 +svn:wc:ra_dav:version-url +V 52 +/spatialindex/!svn/ver/62/spatialindex/trunk/AUTHORS +END +ChangeLog +K 25 +svn:wc:ra_dav:version-url +V 55 +/spatialindex/!svn/ver/199/spatialindex/trunk/ChangeLog +END +depcomp +K 25 +svn:wc:ra_dav:version-url +V 51 +/spatialindex/!svn/ver/2/spatialindex/trunk/depcomp +END +spatialindex.suo +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/203/spatialindex/trunk/spatialindex.suo +END +README +K 25 +svn:wc:ra_dav:version-url +V 52 +/spatialindex/!svn/ver/203/spatialindex/trunk/README +END +INSTALL.WIN +K 25 +svn:wc:ra_dav:version-url +V 57 +/spatialindex/!svn/ver/106/spatialindex/trunk/INSTALL.WIN +END +configure.ac +K 25 +svn:wc:ra_dav:version-url +V 58 +/spatialindex/!svn/ver/199/spatialindex/trunk/configure.ac +END +INSTALL +K 25 +svn:wc:ra_dav:version-url +V 52 +/spatialindex/!svn/ver/75/spatialindex/trunk/INSTALL +END +COPYING +K 25 +svn:wc:ra_dav:version-url +V 51 +/spatialindex/!svn/ver/2/spatialindex/trunk/COPYING +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 57 +/spatialindex/!svn/ver/189/spatialindex/trunk/Makefile.am +END +missing +K 25 +svn:wc:ra_dav:version-url +V 51 +/spatialindex/!svn/ver/2/spatialindex/trunk/missing +END +autogen.sh +K 25 +svn:wc:ra_dav:version-url +V 55 +/spatialindex/!svn/ver/44/spatialindex/trunk/autogen.sh +END +NEWS +K 25 +svn:wc:ra_dav:version-url +V 48 +/spatialindex/!svn/ver/2/spatialindex/trunk/NEWS +END +install-sh +K 25 +svn:wc:ra_dav:version-url +V 54 +/spatialindex/!svn/ver/2/spatialindex/trunk/install-sh +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/.svn/dir-prop-base new file mode 100644 index 000000000..710cc907e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/dir-prop-base @@ -0,0 +1,20 @@ +K 10 +svn:ignore +V 147 +Makefile +Makefile.in +libtool +configure +config.log +config.status +config.guess +config.sub +autom4te.cache +.libs +aclocal.m4 +.deps +ltmain.sh +*.bz2 +*.gz + +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/entries b/sci-libs/libspatialindex/svn/trunk/.svn/entries new file mode 100644 index 000000000..3cefe7e25 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/entries @@ -0,0 +1,652 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk +http://svn.gispython.org/spatialindex + + + +2011-05-18T15:20:08.186979Z +203 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +HOWTORELEASE.txt +file + + + + +2011-08-01T00:42:34.941167Z +fd5e6466719bdf7d4f2a2831fb93a9e3 +2010-03-05T14:19:51.578751Z +178 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +2086 + +spatialindex.sln +file + + + + +2011-08-01T00:42:34.941167Z +90029cb0f3beefca12a84ccc350807de +2009-07-22T15:18:42.091942Z +112 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +5948 + +mkinstalldirs +file + + + + +2011-08-01T00:42:34.941167Z +cfbd1f0cc32bb4f6feb804354401e61a +2008-04-29T18:03:50.201853Z +75 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +3421 + +regressiontest +dir + +include +dir + +makefile.vc +file + + + + +2011-08-01T00:42:34.945167Z +2da5d6e2c73779033a306b0a93fb7279 +2010-12-04T21:22:32.514652Z +199 +hobu + + + + + + + + + + + + + + + + + + + + + +7044 + +AUTHORS +file + + + + +2011-08-01T00:42:34.945167Z +c9b5ecb6aa425ce8962ad5f522951705 +2008-01-19T18:37:39.389909Z +62 +hobu + + + + + + + + + + + + + + + + + + + + + +147 + +ChangeLog +file + + + + +2011-08-01T00:42:34.945167Z +04ead0a3343ea4c13d62d75fecb0b001 +2010-12-04T21:22:32.514652Z +199 +hobu + + + + + + + + + + + + + + + + + + + + + +36795 + +depcomp +file + + + + +2011-08-01T00:42:34.945167Z +e181e2c8720c60522c4c4c981108e367 +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +15205 + +src +dir + +spatialindex.suo +file + + + + +2011-08-01T00:42:34.945167Z +1816e890081a67e65fca615bf1b9e8f5 +2011-05-18T15:20:08.186979Z +203 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +195072 + +spatialindex-vc +dir + +README +file + + + + +2011-08-01T00:42:34.949134Z +27ea41808f9c80b750d7561645a91419 +2011-05-18T15:20:08.186979Z +203 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +21730 + +INSTALL.WIN +file + + + + +2011-08-01T00:42:34.949134Z +441f8f9aba5ec1e8ebb71cd1fa942e8b +2009-07-19T01:26:54.003010Z +106 +mhadji + + + + + + + + + + + + + + + + + + + + + +831 + +configure.ac +file + + + + +2011-08-01T00:42:34.949134Z +e8ca308c5d7c89c72cbd78dcc1829f28 +2010-12-04T21:22:32.514652Z +199 +hobu + + + + + + + + + + + + + + + + + + + + + +2257 + +INSTALL +file + + + + +2011-08-01T00:42:34.949134Z +5d4638159851671944108691f23e4f28 +2008-04-29T18:03:50.201853Z +75 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +9273 + +COPYING +file + + + + +2011-08-01T00:42:34.949134Z +fbc093901857fcd118f065f900982c24 +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +26436 + +missing +file + + + + +2011-08-01T00:42:34.949134Z +fd5dd60aa8cefab9462677280ea74a61 +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +10587 + +Makefile.am +file + + + + +2011-08-01T00:42:34.949134Z +a54749f5751c911a46f8e0e35f7a685a +2010-09-16T13:56:14.957953Z +189 +hobu + + + + + + + + + + + + + + + + + + + + + +725 + +autogen.sh +file + + + + +2011-08-01T00:42:34.949134Z +f535d156563a1c45c84cf546d418017f +2008-01-17T17:06:18.561657Z +44 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +938 + +NEWS +file + + + + +2011-08-01T00:42:34.949134Z +d41d8cd98f00b204e9800998ecf8427e +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +0 + +install-sh +file + + + + +2011-08-01T00:42:34.949134Z +2947b9daa4c6c8bddac15717f3548ab6 +2007-08-01T20:37:49.786254Z +2 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +9206 + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/HOWTORELEASE.txt.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/HOWTORELEASE.txt.svn-base new file mode 100644 index 000000000..1f66a2852 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/HOWTORELEASE.txt.svn-base @@ -0,0 +1,5 @@ +K 12 +svn:keywords +V 18 +Id Rev Date Author +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/INSTALL.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/INSTALL.svn-base new file mode 100644 index 000000000..f59aac5c2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/INSTALL.svn-base @@ -0,0 +1,9 @@ +K 12 +svn:keywords +V 18 +Id Rev Author Date +K 13 +svn:mime-type +V 10 +text/x-rst +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/README.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/README.svn-base new file mode 100644 index 000000000..f59aac5c2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/README.svn-base @@ -0,0 +1,9 @@ +K 12 +svn:keywords +V 18 +Id Rev Author Date +K 13 +svn:mime-type +V 10 +text/x-rst +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/autogen.sh.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/autogen.sh.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/autogen.sh.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/install-sh.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/install-sh.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/install-sh.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/mkinstalldirs.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/mkinstalldirs.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/mkinstalldirs.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/spatialindex.sln.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/spatialindex.sln.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/spatialindex.sln.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/spatialindex.suo.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/spatialindex.suo.svn-base new file mode 100644 index 000000000..dbc918b06 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/prop-base/spatialindex.suo.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/AUTHORS.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/AUTHORS.svn-base new file mode 100644 index 000000000..c68fc7c6f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/AUTHORS.svn-base @@ -0,0 +1,5 @@ +Marios Hadjieleftheriou -- Main author +mhadji@gmail.com + +Howard Butler -- minor packaging, Trac/SVN stuff, and some Windows work +hobu.inc@gmail.com
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/COPYING.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/COPYING.svn-base new file mode 100644 index 000000000..5ab7695ab --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/COPYING.svn-base @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/ChangeLog.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/ChangeLog.svn-base new file mode 100644 index 000000000..9e1c580d6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/ChangeLog.svn-base @@ -0,0 +1,1206 @@ +2010-11-22 19:53 seang + + * src/capi/sidx_api.cc: Fix test of length value + +2010-11-22 19:23 hobu + + * src/capi/sidx_api.cc: whitespace normalization + +2010-11-22 19:00 seang + + * src/capi/sidx_api.cc: Add up deltas for multidimensional input + +2010-11-22 18:49 seang + + * src/capi/sidx_api.cc: Add up deltas for multidimensional input + +2010-11-22 18:46 hobu + + * src/capi/sidx_api.cc: revert r193 + +2010-11-22 16:02 hobu + + * src/capi/sidx_api.cc: we should set isPoint to true if we pass + our epsilon test -- this didn't work before + +2010-10-14 13:18 mhadji + + * include/tools/Tools.h, src/tools/Tools.cc: Removed + nextUnifromLongDouble. It was incorrect + +2010-10-13 15:10 mhadji + + * include/tools/Tools.h, src/tools/Tools.cc: Added + nextUniformLongDouble + +2010-09-16 13:56 hobu + + * Makefile.am: fix #25 and include visual studio files in the + release + +2010-09-16 13:53 hobu + + * makefile.vc: bump versions in preparation for release + +2010-09-16 13:52 hobu + + * configure.ac, include/Version.h: bump versions in preparation for + release + +2010-06-19 20:34 hobu + + * include/capi/CustomStorage.h, include/capi/Index.h, + include/capi/Makefile.am, include/capi/sidx_api.h, + include/capi/sidx_config.h, include/capi/sidx_impl.h, + makefile.vc, src/capi/CustomStorage.cc, src/capi/Index.cc, + src/capi/Makefile.am, src/capi/Utility.cc, src/capi/sidx_api.cc: + add Matthias' CustomStorage backend for C API + +2010-04-21 18:50 hobu + + * README: Add Marios' pagesize diatribe to the docs + +2010-04-12 19:56 hobu + + * ChangeLog: update ChangeLog + +2010-04-12 17:17 mhadji + + * regressiontest/rtree/Exhaustive.cc: + +2010-04-12 17:07 mhadji + + * regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/test3/run, spatialindex.suo, + src/rtree/BulkLoader.cc: Fixed rtree/BulkLoader infinit loop bug + +2010-03-31 15:33 hobu + + * src/capi/BoundsQuery.cc, src/capi/CountVisitor.cc, + src/capi/DataStream.cc, src/capi/IdVisitor.cc, src/capi/Index.cc, + src/capi/ObjVisitor.cc, src/capi/Utility.cc: format and layout + normalization + +2010-03-30 20:18 hobu + + * src/spatialindex/MovingRegion.cc: ensure that we instantiate the + ivOut with at least the ivIn so we have a properly constructed + Tools::Interval #16 + +2010-03-05 14:19 hobu + + * ., HOWTORELEASE.txt: add doc describing how to release + +2010-03-05 02:56 hobu + + * regressiontest/tprtree/test1, regressiontest/tprtree/test2: + propsets to ignore test output: + +2010-03-05 02:53 hobu + + * configure.ac: use subdir-objects for automake and rename the make + dist output to spatialindex-src + +2010-03-05 02:52 hobu + + * include/Version.h: increment version info in preparation for + release + +2010-03-05 01:59 hobu + + * ChangeLog: update for release + +2010-03-04 16:33 hobu + + * include/capi/CountVisitor.h, include/capi/Makefile.am, + include/capi/sidx_api.h, include/capi/sidx_impl.h, makefile.vc, + src/capi/CountVisitor.cc, src/capi/Makefile.am, + src/capi/sidx_api.cc: add CountVisitor to the CAPI to provide a + cumulation of the number of hits that land within a query + +2010-03-03 21:55 hobu + + * include/capi/IdVisitor.h, include/capi/ObjVisitor.h, + include/capi/sidx_api.h, regressiontest/rtree/test3/run, + src/capi/LeafQuery.cc, src/capi/sidx_api.cc: use uint64_t for + result counts instead of uint32_t in C API + +2009-12-29 02:35 hobu + + * regressiontest/mvrtree/Exhaustive.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/tprtree/Exhaustive.cc: fix up for gcc 4.4 + +2009-12-04 21:57 mhadji + + * spatialindex.suo, src/spatialindex/Region.cc: + +2009-12-04 18:46 mhadji + + * src/spatialindex/Region.cc: Fixed Region::touchesRegion member + function bug. + +2009-11-05 16:26 hobu + + * src/spatialindex/Region.cc: don't thrown an error when -DDEBUG is + on and we initialize an infinite Region + +2009-11-03 03:10 hobu + + * src/capi/sidx_api.cc: pass in a reference for the query bounds + +2009-11-03 03:04 hobu + + * src/capi/sidx_api.cc: try to do no harm when calling Index_Free + on something that's null + +2009-11-03 03:00 hobu + + * src/capi/sidx_api.cc: pass in a reference for the query bounds + +2009-11-03 02:15 hobu + + * src/capi/sidx_api.cc: copy the array using memcpy because we + can't free() something created with new + +2009-11-03 01:48 hobu + + * src/capi/sidx_api.cc: put the data in a newly malloc'd array to + match our std::free call of Index_Delete + +2009-11-02 21:32 hobu + + * src/capi/LeafQuery.cc: make sure to delete our shape when we're + done + +2009-11-02 21:32 hobu + + * src/capi/sidx_api.cc: get dimension from the Region, no need to + fetch from index properties + +2009-11-02 20:53 hobu + + * src/capi/sidx_api.cc: make sure we clean up the bounds and region + +2009-11-02 20:08 hobu + + * regressiontest/mvrtree/Generator.cc, + regressiontest/rtree/Generator.cc, + regressiontest/tprtree/Generator.cc, + regressiontest/tprtree/TPRTreeLoad.cc, + regressiontest/tprtree/TPRTreeQuery.cc, src/capi/sidx_api.cc, + src/mvrtree/Index.cc, src/mvrtree/MVRTree.cc, + src/mvrtree/Node.cc, src/rtree/Index.cc, src/rtree/Node.cc, + src/rtree/RTree.cc, src/spatialindex/LineSegment.cc, + src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, src/spatialindex/TimePoint.cc, + src/spatialindex/TimeRegion.cc, src/tools/Tools.cc, + src/tprtree/Index.cc, src/tprtree/Node.cc, + src/tprtree/TPRTree.cc: only #include <limits> where needed, and + not in the global Tools.h file + +2009-10-30 17:09 hobu + + * include/tools/Tools.h, regressiontest/mvrtree/Exhaustive.cc, + regressiontest/mvrtree/Generator.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/Generator.cc, + regressiontest/tprtree/Generator.cc, src/mvrtree/Node.cc, + src/rtree/BulkLoader.cc, src/rtree/Node.cc, src/rtree/RTree.cc, + src/spatialindex/LineSegment.cc, src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, + src/storagemanager/RandomEvictionsBuffer.cc, src/tprtree/Node.cc: + remove <cmath> <limits> and <climits> from Tools.h and include + them seperately in each file that needs them + +2009-10-30 16:37 hobu + + * include/capi/sidx_api.h: define to denote we're C API + +2009-10-30 15:03 hobu + + * include/capi/sidx_config.h: add a newline + +2009-10-22 02:42 hobu + + * src/capi/sidx_api.cc: make sure we use new/delete instead of + new/free + +2009-10-21 17:35 hobu + + * ., include/LineSegment.h, include/Point.h, include/Region.h, + include/SpatialIndex.h, include/capi, src/capi, + src/spatialindex/LineSegment.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc: remove namespace pollution of Tools:: + into the globally include'd header SpatialIndex.h + +2009-10-20 15:24 hobu + + * configure.ac, makefile.vc: bump versions in preparation for + release + +2009-10-19 20:31 hobu + + * include/capi/sidx_api.h: add SIDX_Version prototype + +2009-10-19 20:23 hobu + + * ltmain.sh: ltmain.sh doesn't belong in svn + +2009-10-19 20:23 hobu + + * include/capi/Makefile.in, src/capi/Makefile.in: Makefile.in's + don't belong in svn + +2009-10-19 18:50 hobu + + * makefile.vc: C API compilation fix + +2009-10-19 18:50 hobu + + * src/tools/Tools.cc: tmpname fixes so we compile on msvc2003 + +2009-10-19 18:29 hobu + + * makefile.vc: don't define a variable to "" or cl will complain + +2009-10-08 19:32 hobu + + * src/rtree/BulkLoader.cc: bleaf and bindex switched around in + createLevel call + +2009-09-17 20:40 hobu + + * include/capi/LeafQuery.h, include/capi/sidx_api.h, + src/capi/LeafQuery.cc, src/capi/sidx_api.cc: more leaf querying + code + +2009-09-16 18:45 hobu + + * include/capi/LeafQuery.h, include/capi/Makefile.am, + include/capi/Makefile.in, include/capi/sidx_impl.h, + src/capi/LeafQuery.cc, src/capi/Makefile.am, + src/capi/Makefile.in, src/capi/sidx_api.cc: add beginnings of + leaf querying to C API + +2009-09-16 03:34 hobu + + * include/capi/Item.h, include/capi/ObjVisitor.h, + include/capi/sidx_config.h, include/capi/sidx_impl.h, + src/capi/Item.cc, src/capi/Makefile.am, src/capi/Makefile.in, + src/capi/ObjVisitor.cc, src/capi/sidx_api.cc: remove the + duplicate and unnecessary Item construct that was masking the + already existing IData interface + +2009-08-31 15:32 hobu + + * makefile.vc: support building the c api + +2009-08-24 13:25 hobu + + * regressiontest/mvrtree/Exhaustive.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/tprtree/Exhaustive.cc: fix issue with uint32_t by + copying macros from Tools.h + +2009-08-19 20:47 hobu + + * Makefile.am: try to ensure -lstdc++ is linked + +2009-08-19 19:56 hobu + + * include/capi, src/capi: ignores + +2009-08-19 16:37 hobu + + * Makefile.am, configure.ac, include/Makefile.am, include/capi, + include/capi/BoundsQuery.h, include/capi/DataStream.h, + include/capi/Error.h, include/capi/IdVisitor.h, + include/capi/Index.h, include/capi/Item.h, + include/capi/Makefile.am, include/capi/Makefile.in, + include/capi/ObjVisitor.h, include/capi/Utility.h, + include/capi/sidx_api.h, include/capi/sidx_config.h, + include/capi/sidx_impl.h, include/tools/Makefile.am, + src/Makefile.am, src/capi, src/capi/BoundsQuery.cc, + src/capi/DataStream.cc, src/capi/Error.cc, src/capi/IdVisitor.cc, + src/capi/Index.cc, src/capi/Item.cc, src/capi/Makefile.am, + src/capi/Makefile.in, src/capi/ObjVisitor.cc, + src/capi/Utility.cc, src/capi/sidx_api.cc: add C API (not + currently built on windows) + +2009-08-19 15:25 hobu + + * .: ignore propset + +2009-08-19 15:24 hobu + + * regressiontest/mvrtree/test1, regressiontest/mvrtree/test2, + regressiontest/rtree, regressiontest/rtree/test1, + regressiontest/rtree/test2, regressiontest/rtree/test3, + regressiontest/rtree/test4, regressiontest/tprtree/test1, + regressiontest/tprtree/test2: propsets to ignore test results + +2009-08-18 18:07 hobu + + * include/tools/Tools.h, src/tools/Tools.cc: locking for + Tools::PropertySet (commented out though because it doesn't work + +2009-08-14 17:41 hobu + + * src/tools/Tools.cc: comment out PropertySet locking for now + +2009-08-14 15:19 hobu + + * include/tools/Tools.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/rtree/RTree.cc, src/rtree/RTree.h, + src/tools/Tools.cc, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: use HAVE_PTHREAD_H for #ifdef, make + Tools::PropertySet threadsafe for read/write + +2009-08-13 19:10 mhadji + + * spatialindex.suo, src/rtree/BulkLoader.cc, + src/rtree/BulkLoader.h, src/rtree/RTree.cc: + +2009-08-13 15:42 mhadji + + * spatialindex-vc/spatialindex.vcproj, spatialindex.suo: + +2009-08-13 15:24 mhadji + + * include/LineSegment.h, include/MVRTree.h, include/MovingPoint.h, + include/MovingRegion.h, include/Point.h, include/RTree.h, + include/Region.h, include/SpatialIndex.h, include/TPRTree.h, + include/TimePoint.h, include/TimeRegion.h, + include/tools/PointerPool.h, include/tools/Tools.h, + regressiontest/rtree/RTreeBulkLoad.cc, + regressiontest/rtree/RTreeQuery.cc, + regressiontest/rtree/test1/run, regressiontest/rtree/test2/run, + spatialindex.suo, src/mvrtree/Index.cc, src/mvrtree/Index.h, + src/mvrtree/Leaf.cc, src/mvrtree/Leaf.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/mvrtree/PointerPoolNode.h, src/mvrtree/Statistics.cc, + src/mvrtree/Statistics.h, src/rtree/BulkLoader.cc, + src/rtree/BulkLoader.h, src/rtree/Index.cc, src/rtree/Index.h, + src/rtree/Leaf.cc, src/rtree/Leaf.h, src/rtree/Node.cc, + src/rtree/Node.h, src/rtree/PointerPoolNode.h, + src/rtree/RTree.cc, src/rtree/RTree.h, src/rtree/Statistics.cc, + src/rtree/Statistics.h, src/spatialindex/LineSegment.cc, + src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, src/spatialindex/TimePoint.cc, + src/spatialindex/TimeRegion.cc, src/storagemanager/Buffer.cc, + src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, + src/storagemanager/RandomEvictionsBuffer.cc, src/tools/Tools.cc, + src/tprtree/Index.cc, src/tprtree/Index.h, src/tprtree/Leaf.cc, + src/tprtree/Leaf.h, src/tprtree/Node.cc, src/tprtree/Node.h, + src/tprtree/PointerPoolNode.h, src/tprtree/Statistics.cc, + src/tprtree/Statistics.h, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: 1. Replace size_t with uint32_t to fix + 64/32 bit compatibility issues + 2. Fixed memory bug related to data array and bulk loading for + RTree. + +2009-08-10 13:35 hobu + + * include/SpatialIndex.h, include/tools/Tools.h: remove #define + interface, use class + +2009-08-06 01:11 hobu + + * makefile.vc: osgeo4w packaging + +2009-08-05 20:21 hobu + + * include/tools/Tools.h: don't redefine interface if it is already + defined (/me scowls at windows + +2009-08-05 19:27 hobu + + * src/rtree/BulkLoader.cc: comment out record deletion entirely + +2009-08-05 17:58 hobu + + * src/rtree/BulkLoader.cc: guard against invalid delete + +2009-07-30 18:48 hobu + + * Makefile.am, configure.ac: bump version to 1.4.0 in prep for + release, add a windows docs to the dist + +2009-07-30 16:57 hobu + + * src/storagemanager/DiskStorageManager.cc: Add a + CheckFilesExists(Tools::PropertySet&) method instead of the cheap + way we were checking for existence before. This takes into + account the file extensions and only returns true if both files + exist + +2009-07-30 16:56 hobu + + * include/tools/Tools.h: move the warning about 4251 down into + _MSC_VER + +2009-07-30 03:10 hobu + + * ChangeLog, configure.ac: new changelog + +2009-07-30 02:32 hobu + + * makefile.vc: update for new layout. make sure to build dll + appropriately + +2009-07-29 21:24 hobu + + * include/tools/Tools.h: turn off warning 4251 + +2009-07-29 20:57 hobu + + * include/Makefile.am, include/SpatialIndex.h, include/Version.h: + fix #15 and provide a way to determine the library version at + compile time + +2009-07-29 20:50 hobu + + * makefile.vc: add back makefile.vc + +2009-07-22 19:29 hobu + + * src/spatialindex/Region.cc: a note about the debugging lint that + is incorrect when the bounds are infinity + +2009-07-22 19:24 hobu + + * regressiontest/rtree/Exhaustive.cc: make sure to #include + <cstring> to satisfy gcc 4.3+ + +2009-07-22 15:23 mhadji + + * regressiontest/rtree/RTreeBulkLoad.vcproj, + regressiontest/rtree/RTreeExhaustive.vcproj, + regressiontest/rtree/RTreeGenerator.vcproj, + regressiontest/rtree/RTreeLoad.vcproj, + regressiontest/rtree/RTreeQuery.vcproj, + spatialindex-vc/spatialindex.vcproj, spatialindex.suo: + +2009-07-22 15:18 mhadji + + * spatialindex.sln, spatialindex.suo: + +2009-07-21 13:11 mhadji + + * src/tools/Tools.cc: + +2009-07-20 20:32 hobu + + * src/storagemanager/DiskStorageManager.cc: attempt to fix #8 and + allow users to specify extensions for the dat and idx files of + the diskstorage manager + +2009-07-20 17:35 hobu + + * src/tools/Tools.cc: make sure to update existing values in + setProperties instead of assuming it doesn't exist in the map + +2009-07-20 15:01 mhadji + + * spatialindex.suo, src/mvrtree/MVRTree.cc, src/rtree/RTree.cc, + src/tprtree/TPRTree.cc: + +2009-07-19 14:51 mhadji + + * include/LineSegment.h, include/MVRTree.h, include/MovingPoint.h, + include/MovingRegion.h, include/Point.h, include/RTree.h, + include/Region.h, include/SpatialIndex.h, include/TPRTree.h, + include/TimePoint.h, include/TimeRegion.h, include/tools/Tools.h, + spatialindex.suo: + +2009-07-19 01:26 mhadji + + * INSTALL.WIN: + +2009-07-19 01:15 mhadji + + * spatialindex-vc/spatialindex.vcproj, spatialindex.suo: + +2009-07-19 01:13 mhadji + + * spatialindex.suo: + +2009-07-19 01:09 mhadji + + * makefile.vc, regressiontest/rtree/RTreeBulkLoad.vcproj, + spatialindex.suo: + +2009-07-19 01:02 mhadji + + * INSTALL.WIN, regressiontest/rtree/RTreeBulkLoad.vcproj, + regressiontest/rtree/RTreeExhaustive.vcproj, + regressiontest/rtree/RTreeGenerator.vcproj, + regressiontest/rtree/RTreeLoad.vcproj, + regressiontest/rtree/RTreeQuery.vcproj, + regressiontest/rtree/test3/run, + spatialindex-vc/spatialindex.vcproj, spatialindex.sln, + spatialindex.suo: + +2009-07-18 22:52 mhadji + + * include/SpatialIndex.h, include/tools/Tools.h: + +2009-07-18 22:19 mhadji + + * spatialindex-vc/spatialindex.vcproj.RESEARCH.marioh.user: + +2009-07-18 22:19 mhadji + + * include/LineSegment.h, include/MVRTree.h, include/MovingPoint.h, + include/MovingRegion.h, include/Point.h, include/RTree.h, + include/Region.h, include/SpatialIndex.h, include/TPRTree.h, + include/TimePoint.h, include/TimeRegion.h, + include/tools/Makefile.am, include/tools/PointerPool.h, + include/tools/PoolPointer.h, include/tools/SmartPointer.h, + include/tools/TemporaryFile.h, include/tools/Tools.h, + include/tools/rand48.h, makefile.vc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/Generator.cc, + regressiontest/rtree/RTreeBulkLoad.cc, + regressiontest/rtree/RTreeBulkLoad.vcproj, + regressiontest/rtree/RTreeExhaustive.vcproj, + regressiontest/rtree/RTreeGenerator.vcproj, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeLoad.vcproj, + regressiontest/rtree/RTreeQuery.vcproj, + regressiontest/rtree/test3/run, spatialindex-vc, + spatialindex-vc/spatialindex.vcproj, + spatialindex-vc/spatialindex.vcproj.RESEARCH.marioh.user, + src/mvrtree/Index.cc, src/mvrtree/Index.h, src/mvrtree/Leaf.cc, + src/mvrtree/Leaf.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/mvrtree/PointerPoolNode.h, src/mvrtree/Statistics.h, + src/rtree/BulkLoader.cc, src/rtree/BulkLoader.h, + src/rtree/Index.h, src/rtree/Leaf.h, src/rtree/Node.h, + src/rtree/PointerPoolNode.h, src/rtree/RTree.cc, + src/rtree/RTree.h, src/rtree/Statistics.h, + src/spatialindex/MovingRegion.cc, + src/spatialindex/SpatialIndexImpl.cc, + src/spatialindex/SpatialIndexImpl.h, + src/storagemanager/Buffer.cc, src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, + src/storagemanager/RandomEvictionsBuffer.cc, + src/storagemanager/RandomEvictionsBuffer.h, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/Makefile.am, src/tools/TemporaryFile.cc, + src/tools/Tools.cc, src/tprtree/Index.h, src/tprtree/Leaf.h, + src/tprtree/Node.h, src/tprtree/PointerPoolNode.h, + src/tprtree/Statistics.h, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: + +2009-07-15 14:39 hobu + + * include/SpatialIndex.h, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/rtree/Node.cc, src/rtree/Node.h, src/rtree/RTree.cc, + src/rtree/RTree.h, src/tprtree/Node.cc, src/tprtree/Node.h: apply + Willem's patch for #14 + +2009-07-06 22:23 hobu + + * src/rtree/RTree.cc: more descriptive and separate exception + descriptions for FillFactor inconsistencies + +2009-07-06 14:38 hobu + + * include/SpatialIndex.h, ltmain.sh: silence warnings about windows + compiler complaints on non-windows systems + +2009-05-28 17:52 hobu + + * makefile.vc: rename dlls to not have lib* in front of them + +2009-05-28 16:31 hobu + + * makefile.vc: A much improved windows makefile based in libLAS' + +2009-05-28 16:31 hobu + + * include/SpatialIndex.h: On MSVC, just about every class complains + about 4250, inheritance by dominance. We'll just shut that up for + now. + +2009-05-14 18:26 hobu + + * src/tools/TemporaryFile.cc: apply Patrick Mézard's patch for the + inverted use of mktemp on windows #13 + +2009-05-14 18:21 hobu + + * src/tools/Tools.cc: Fix #12, add time.h so msvc9 works + +2009-05-04 17:10 hobu + + * regressiontest/mvrtree/Exhaustive.cc, + regressiontest/mvrtree/MVRTreeLoad.cc, + regressiontest/mvrtree/MVRTreeQuery.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeQuery.cc, + regressiontest/tprtree/Generator.cc, src/mvrtree/MVRTree.cc, + src/mvrtree/Node.cc, src/rtree/BulkLoader.cc, src/rtree/Leaf.cc, + src/rtree/Node.cc, src/rtree/RTree.cc, + src/spatialindex/LineSegment.cc, src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, src/spatialindex/TimePoint.cc, + src/spatialindex/TimeRegion.cc, src/storagemanager/Buffer.cc, + src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, src/tools/Tools.cc, + src/tprtree/Leaf.cc, src/tprtree/Node.cc, src/tprtree/TPRTree.cc: + apply the patch for #11 - cstring and limits includes so gcc 4.3+ + works + +2008-05-30 19:42 mhadji + + * src/tools/Makefile.am, src/tools/Tools.cc: + +2008-05-23 18:27 mhadji + + * makefile.vc: + +2008-05-23 17:55 mhadji + + * configure.ac: + +2008-05-23 17:28 mhadji + + * regressiontest/rtree/RTreeLoad.cc, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h: + +2008-05-18 12:35 mhadji + + * ltmain.sh: + +2008-04-30 05:39 hobu + + * .: propset to ignore aclocal.m4 + +2008-04-30 05:39 hobu + + * aclocal.m4: aclocal.m4 is autogenerated. removing + +2008-04-30 05:35 hobu + + * ., include, include/tools, regressiontest, + regressiontest/mvrtree, regressiontest/rtree, + regressiontest/tprtree, src, src/mvrtree, src/rtree, + src/spatialindex, src/storagemanager, src/tools, src/tprtree: set + svn:ignore properties for autogenerated files and automake cruft + +2008-04-30 05:27 hobu + + * Makefile.in, include/Makefile.in, include/tools/Makefile.in, + regressiontest/Makefile.in, regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, src/Makefile.in, + src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tools/Makefile.in, src/tprtree/Makefile.in: delete + Makefile.in's from source tree. Use autogen.sh to remake them if + building from svn source yourself + +2008-04-30 05:26 hobu + + * include/tools/Makefile.am: add rand48.h to dist target + +2008-04-29 19:47 mhadji + + * regressiontest/rtree/test1/data, + regressiontest/rtree/test1/queries: + +2008-04-29 18:17 mhadji + + * include/tools/rand48.hpp: + +2008-04-29 18:06 mhadji + + * include/tools/rand48.h: + +2008-04-29 18:03 mhadji + + * INSTALL, Makefile.in, aclocal.m4, configure.ac, mkinstalldirs, + regressiontest/Makefile.in, regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/TemporaryFile.cc, src/tools/Tools.cc: + +2008-04-29 16:36 mhadji + + * makefile.vc: + +2008-04-29 16:36 mhadji + + * include/Makefile.in, include/SpatialIndex.h, + include/tools/Makefile.in, include/tools/Tools.h: + +2008-04-29 16:36 mhadji + + * src/Makefile.in, src/mvrtree/Makefile.in, src/mvrtree/Node.cc, + src/rtree/Makefile.in, src/spatialindex/LineSegment.cc, + src/spatialindex/Makefile.in, src/spatialindex/MovingRegion.cc, + src/storagemanager/Makefile.in, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/Makefile.in, src/tprtree/Makefile.in: + +2008-04-29 15:40 mhadji + + * src/spatialindex/MovingRegion.cc: Fixex malloc memory leak. + +2008-04-29 15:40 mhadji + + * src/spatialindex/LineSegment.cc: Fixed malloc memory leak + +2008-02-26 16:15 hobu + + * src/tools/rand48.cc: oops. Add missing file + +2008-02-26 16:14 hobu + + * include/tools/rand48.hpp: oops. Add missing file + +2008-01-25 19:43 hobu + + * include/MVRTree.h, include/RTree.h, include/SpatialIndex.h, + include/TPRTree.h, include/tools/Tools.h, makefile.vc, + src/mvrtree/Index.cc, src/mvrtree/Leaf.cc, src/mvrtree/Node.cc, + src/rtree/BulkLoader.cc, src/rtree/Index.cc, src/rtree/Leaf.cc, + src/rtree/Node.cc, src/spatialindex/LineSegment.cc, + src/spatialindex/MovingRegion.cc, src/storagemanager/Buffer.cc, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/TemporaryFile.cc, src/tools/Tools.cc, + src/tprtree/Index.cc, src/tprtree/Leaf.cc, src/tprtree/Node.cc: + Initial push of windows patches + +2008-01-23 16:25 mhadji + + * INSTALL: + +2008-01-21 14:19 mhadji + + * README, regressiontest/rtree/test3/run: + +2008-01-19 20:51 hobu + + * configure.ac, makefile.vc: bump version to 1.3 + +2008-01-19 18:42 hobu + + * ChangeLog: Add an auto-generated ChangeLog + +2008-01-19 18:37 hobu + + * AUTHORS: add myself and some notes + +2008-01-19 18:36 hobu + + * INSTALL: update to ReST + +2008-01-19 18:09 hobu + + * README: update ReST + +2008-01-19 18:09 hobu + + * README: update ReST + +2008-01-19 18:03 hobu + + * README: update ReST + +2008-01-19 18:02 hobu + + * README: update ReST + +2008-01-19 18:02 hobu + + * README: update ReST + +2008-01-19 18:01 hobu + + * README: update ReST + +2008-01-19 17:59 hobu + + * README: update ReST + +2008-01-19 17:59 hobu + + * README: update ReST + +2008-01-19 17:58 hobu + + * README: update ReST + +2008-01-19 17:58 hobu + + * README: update ReST + +2008-01-19 17:56 hobu + + * README: update ReST + +2008-01-19 17:55 hobu + + * README: update ReST + +2008-01-19 17:29 hobu + + * README: update ReST + +2008-01-19 17:26 hobu + + * README: update to ReST + +2008-01-19 17:02 hobu + + * README: set mimetype to reStructured text so Trac will render it + for us in the browser + +2008-01-17 23:34 hobu + + * regressiontest/tprtree/Makefile.am, + regressiontest/tprtree/Makefile.in, src/mvrtree/Makefile.am, + src/mvrtree/Makefile.in, src/rtree/Makefile.am, + src/rtree/Makefile.in, src/spatialindex/Makefile.am, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.am, + src/storagemanager/Makefile.in, src/tprtree/Makefile.am, + src/tprtree/Makefile.in: add internal headers to the _SOURCES + targets so they get included in make dist + +2008-01-17 17:06 hobu + + * Makefile.in, aclocal.m4, autogen.sh, include/Makefile.in, + include/tools/Makefile.in, ltmain.sh, regressiontest/Makefile.in, + regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, src/Makefile.in, + src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tools/Makefile.in, src/tprtree/Makefile.in: add autogen.sh to + simplify auto stuff + +2008-01-17 17:04 hobu + + * debian: move debian packaging stuff out of trunk + +2008-01-15 19:33 hobu + + * makefile.vc: add nmake makefile + +2007-12-07 20:44 kenneth + + * debian/libspatialindex1.dirs, debian/libspatialindex1.install, + debian/libspatialindex11.dirs, debian/libspatialindex11.install: + Wrong names + +2007-12-07 19:58 kenneth + + * configure, debian/rules: Fixed rules file + +2007-12-07 18:10 kenneth + + * config.guess, config.sub, debian/control: Updates to the control + file (packaging) + Removal of files that shouldn't be in SVN + +2007-11-30 18:04 mhadji + + * Makefile.in, configure, configure.ac: + +2007-11-30 16:50 seang + + * Makefile.am: Version info to 1:0:0 + +2007-11-29 22:26 mhadji + + * INSTALL, configure, configure.ac: + +2007-11-29 21:54 mhadji + + * include/LineSegment.h, include/Point.h, include/Region.h, + include/tools/LineSegment.h, include/tools/Point.h, + include/tools/Region.h, src/spatialindex/LineSegment.cc, + src/spatialindex/Point.cc, src/spatialindex/Region.cc, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/TemporaryFile.cc, src/tools/Tools.cc: + +2007-11-29 21:48 mhadji + + * Makefile.am, Makefile.in, aclocal.m4, configure, configure.ac, + include/Makefile.am, include/Makefile.in, include/MovingPoint.h, + include/MovingRegion.h, include/SpatialIndex.h, + include/TimePoint.h, include/TimeRegion.h, + include/tools/Makefile.am, include/tools/Makefile.in, + include/tools/PointerPool.h, include/tools/PoolPointer.h, + include/tools/SmartPointer.h, include/tools/TemporaryFile.h, + include/tools/Tools.h, regressiontest/Makefile.in, + regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Generator.cc, + regressiontest/tprtree/Makefile.in, + regressiontest/tprtree/RandomGenerator.cc, + regressiontest/tprtree/RandomGenerator.h, src/Makefile.in, + src/mvrtree/Index.cc, src/mvrtree/Leaf.cc, + src/mvrtree/MVRTree.cc, src/mvrtree/Makefile.in, + src/mvrtree/Node.cc, src/mvrtree/Statistics.cc, + src/rtree/BulkLoader.cc, src/rtree/Index.cc, src/rtree/Leaf.cc, + src/rtree/Makefile.in, src/rtree/Node.cc, src/rtree/RTree.cc, + src/rtree/Statistics.cc, src/spatialindex/Makefile.am, + src/spatialindex/Makefile.in, src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, + src/spatialindex/SpatialIndexImpl.h, + src/spatialindex/TimePoint.cc, src/spatialindex/TimeRegion.cc, + src/storagemanager/Buffer.cc, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/Makefile.in, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/Makefile.am, src/tools/Makefile.in, src/tools/geometry, + src/tools/tools, src/tprtree/Index.cc, src/tprtree/Leaf.cc, + src/tprtree/Makefile.in, src/tprtree/Node.cc, + src/tprtree/Statistics.cc, src/tprtree/TPRTree.cc: + +2007-11-29 18:00 seang + + * debian, debian/README, debian/README.Debian, debian/changelog, + debian/compat, debian/control, debian/copyright, debian/dirs, + debian/docs, debian/libspatialindex1-dev.dirs, + debian/libspatialindex1-dev.install, + debian/libspatialindex1.doc-base.EX, + debian/libspatialindex11.dirs, debian/libspatialindex11.install, + debian/rules: Add debian directory created by dh_make + +2007-11-29 04:05 hobu + + * Makefile.am, Makefile.in: use -version-info instead of -release + +2007-11-29 00:59 hobu + + * include/Makefile.in, include/tools/Makefile.in: include + Makefile.in's + +2007-11-29 00:55 hobu + + * Makefile.am, Makefile.in: use .'s to separate version info and + don't do -no-undefined + +2007-11-29 00:19 hobu + + * Makefile.am: tweak formatting + +2007-11-29 00:11 seang + + * Makefile.am: Add version-info to Makefile.am + +2007-11-28 23:54 hobu + + * Makefile.am, Makefile.in, include/Makefile.am, + include/tools/Makefile.am: finish incorporating -ltools + +2007-11-28 22:48 hobu + + * Makefile.am, Makefile.in, configure, configure.ac, + include/Makefile.am, include/tools/Makefile.am: more progress on + automake for includes directories... close, but not quite + +2007-11-28 22:38 hobu + + * include/Makefile.am, include/tools/Makefile.am: Add automake + files for includes + +2007-11-28 21:03 hobu + + * Makefile.am, Makefile.in, aclocal.m4, configure, configure.ac, + include/tools, regressiontest/Makefile.in, + regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, src/Makefile.am, + src/Makefile.in, src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tools, src/tools/Makefile.in, src/tools/geometry/Makefile.am, + src/tools/geometry/Makefile.in, src/tools/tools/Makefile.am, + src/tools/tools/Makefile.in, src/tprtree/Makefile.in: start + incorporating -ltools into the tree + +2007-08-30 15:16 mhadji + + * INSTALL, a: README should be INSTALL, and INSTALL should be + README + +2007-08-30 15:15 mhadji + + * INSTALL, README: README should be INSTALL, and INSTALL should be + README + +2007-08-30 15:13 mhadji + + * README, a: README file should be INSTALL, and INSTALL should be + README + +2007-08-02 04:37 hobu + + * src/storagemanager/DiskStorageManager.cc: revert r9 + +2007-08-02 04:37 hobu + + * src/rtree/Leaf.cc: revert r10 + +2007-08-02 04:36 hobu + + * src/rtree/Node.cc: revert r11 + +2007-08-02 04:36 hobu + + * src/rtree/RTree.cc: revert r12 + +2007-08-02 04:35 hobu + + * src/mvrtree/MVRTree.cc: revert r13 + +2007-08-02 04:34 hobu + + * src/spatialindex/SpatialIndexImpl.h: add strings.h + +2007-08-02 04:27 hobu + + * src/mvrtree/MVRTree.cc: add strings.h + +2007-08-02 04:26 hobu + + * src/rtree/RTree.cc: add strings.h + +2007-08-02 04:25 hobu + + * src/rtree/Node.cc: add strings.h + +2007-08-02 02:23 hobu + + * src/rtree/Leaf.cc: include <strings.h> + +2007-08-02 02:21 hobu + + * src/storagemanager/DiskStorageManager.cc: include <strings.h> in + DiskStorageManager (this is not available on Solaris by default) + +2007-08-01 20:49 hobu + + * regressiontest/rtree/test1/data, + regressiontest/rtree/test1/queries: add data and queries for + tests + +2007-08-01 20:48 hobu + + * INSTALL, Makefile.in, README, aclocal.m4, + regressiontest/Makefile.in, regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeQuery.cc, + regressiontest/tprtree/Makefile.in, src/Makefile.in, + src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tprtree/Makefile.in: add Marios' latest updates + +2007-08-01 20:40 hobu + + * spatialindex.111.zip: oops, don't include zip files + +2007-08-01 20:37 hobu + + * AUTHORS, COPYING, ChangeLog, INSTALL, Makefile.am, Makefile.in, + NEWS, README, aclocal.m4, config.guess, config.sub, configure, + configure.ac, depcomp, include, include/MVRTree.h, + include/MovingPoint.h, include/MovingRegion.h, include/RTree.h, + include/SpatialIndex.h, include/TPRTree.h, include/TimePoint.h, + include/TimeRegion.h, install-sh, ltmain.sh, missing, + mkinstalldirs, regressiontest, regressiontest/Makefile.am, + regressiontest/Makefile.in, regressiontest/mvrtree, + regressiontest/mvrtree/Exhaustive.cc, + regressiontest/mvrtree/Generator.cc, + regressiontest/mvrtree/MVRTreeLoad.cc, + regressiontest/mvrtree/MVRTreeQuery.cc, + regressiontest/mvrtree/Makefile.am, + regressiontest/mvrtree/Makefile.in, regressiontest/mvrtree/test1, + regressiontest/mvrtree/test1/run, regressiontest/mvrtree/test2, + regressiontest/mvrtree/test2/run, regressiontest/rtree, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/Generator.cc, + regressiontest/rtree/Makefile.am, + regressiontest/rtree/Makefile.in, + regressiontest/rtree/RTreeBulkLoad.cc, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeQuery.cc, regressiontest/rtree/test1, + regressiontest/rtree/test1/run, regressiontest/rtree/test2, + regressiontest/rtree/test2/run, regressiontest/rtree/test3, + regressiontest/rtree/test3/run, regressiontest/rtree/test4, + regressiontest/rtree/test4/run, regressiontest/tprtree, + regressiontest/tprtree/Exhaustive.cc, + regressiontest/tprtree/Generator.cc, + regressiontest/tprtree/Makefile.am, + regressiontest/tprtree/Makefile.in, + regressiontest/tprtree/RandomGenerator.cc, + regressiontest/tprtree/RandomGenerator.h, + regressiontest/tprtree/TPRTreeLoad.cc, + regressiontest/tprtree/TPRTreeQuery.cc, + regressiontest/tprtree/test1, regressiontest/tprtree/test1/run, + regressiontest/tprtree/test2, regressiontest/tprtree/test2/run, + spatialindex.111.zip, src, src/Makefile.am, src/Makefile.in, + src/mvrtree, src/mvrtree/Index.cc, src/mvrtree/Index.h, + src/mvrtree/Leaf.cc, src/mvrtree/Leaf.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/mvrtree/Makefile.am, + src/mvrtree/Makefile.in, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/mvrtree/PointerPoolNode.h, src/mvrtree/Statistics.cc, + src/mvrtree/Statistics.h, src/rtree, src/rtree/BulkLoader.cc, + src/rtree/BulkLoader.h, src/rtree/Index.cc, src/rtree/Index.h, + src/rtree/Leaf.cc, src/rtree/Leaf.h, src/rtree/Makefile.am, + src/rtree/Makefile.in, src/rtree/Node.cc, src/rtree/Node.h, + src/rtree/PointerPoolNode.h, src/rtree/RTree.cc, + src/rtree/RTree.h, src/rtree/Statistics.cc, + src/rtree/Statistics.h, src/spatialindex, + src/spatialindex/Makefile.am, src/spatialindex/Makefile.in, + src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, + src/spatialindex/SpatialIndexImpl.cc, + src/spatialindex/SpatialIndexImpl.h, + src/spatialindex/TimePoint.cc, src/spatialindex/TimeRegion.cc, + src/storagemanager, src/storagemanager/Buffer.cc, + src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h, + src/storagemanager/Makefile.am, src/storagemanager/Makefile.in, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, + src/storagemanager/RandomEvictionsBuffer.cc, + src/storagemanager/RandomEvictionsBuffer.h, src/tprtree, + src/tprtree/Index.cc, src/tprtree/Index.h, src/tprtree/Leaf.cc, + src/tprtree/Leaf.h, src/tprtree/Makefile.am, + src/tprtree/Makefile.in, src/tprtree/Node.cc, src/tprtree/Node.h, + src/tprtree/PointerPoolNode.h, src/tprtree/Statistics.cc, + src/tprtree/Statistics.h, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: add 1.1.1 version of library + +2007-08-01 20:32 hobu + + * .: basic layout + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/HOWTORELEASE.txt.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/HOWTORELEASE.txt.svn-base new file mode 100644 index 000000000..4853b3b23 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/HOWTORELEASE.txt.svn-base @@ -0,0 +1,82 @@ + +Steps for Making a libLAS Release +============================================================================== + +:Author: Howard Butler +:Contact: hobu.inc@gmail.com +:Revision: $Revision$ +:Date: $Date$ + +This document describes the process for releasing a new version of libspatialindex. + +General Notes +------------------------------------------------------------------------------ + +Release Process + +1) Increment Version Numbers + + - configure.ac + * sidx_version_major + * sidx_version_minor + * sidx_version_micro + - include/Version.h + * SIDX_VERSION_MAJOR + * SIDX_VERSION_MINOR + * SIDX_VERSION_REV + * SIDX_RELEASE_NAME + - makefile.vc's + *PACKAGE_VERSION + +2) Update README to include any relevant info about the release that + might have changed. + +3) Update ChangeLog with svn2cl + +4) Run the regression tests. Really. + +5) Build Windows version + + - Issue nmake and nmake install commands + + :: + + nmake /f makefile.vc clean + nmake /f makefile.vc + nmake /f makefile.vc install + nmake /f makefile.vc package + + +6) Make the source distribution + + :: + + make dist + + +7) Generate MD5 sums + + :: + + md5 spatialindex-src-1.5.0.tar.bz2 > spatialindex-src-1.5.0.tar.bz2.md5 + md5 spatialindex-src-1.5.0.tar.gz > spatialindex-src-1.5.0.tar.gz.md5 + md5 liblas-1.3.1-win32.zip > liblas-1.3.1-win32.zip.md5 + +8) Update http://trac.gispython.org/spatialindex/wiki/Releases + +9) Upload windows and source package as attachments to the new release page. + +10) Tag the release. Use the ``-f`` switch if you are retagging because you + missed something. + + :: + + svn cp http://svn.gispython.org/svn/spatialindex/spatialindex/trunk http://svn.gispython.org/svn/spatialindex/spatialindex/tags/1.5.0 + +11) Write the release notes. Place a copy of the release notes on the release + page you created as well as send an email to spatalindex list announcing the + new release. + + + +$Id$ diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/INSTALL.WIN.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/INSTALL.WIN.svn-base new file mode 100644 index 000000000..52649de1a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/INSTALL.WIN.svn-base @@ -0,0 +1,28 @@ +Visual Studio 2005: +You have to open the spatialindex.sln solution from the IDE and build. +Unfortunatelly, vcbuild.exe does not work as expected, hence you cannot +build the DLL from the command line. + +Visutal Studio 2008: +Either use the IDE or use vcbuild to compile from the command line: + +To create 32bit DLL: +1. Open a Visual Studio command prompt (or open any shell + and run vcvars32.bat). + +2a. Release build: + Run vcbuild.exe /useenv spatialindex.sln "Release|Win32" +2b. Debug build: + Run vcbuild.exe /useenv spatialindex.sln "Debug|Win32" + +To create 64bit DLL: +1. Open a Visual Studio x64 command prompt (or open any shell + and run vcvarsall.bat x64). + +2a. Release build: + Run vcbuild.exe /useenv spatialindex.sln "Release|x64" +2b. Debug build: + Run vcbuild.exe /useenv spatialindex.sln "Debug|x64" + +Enjoy! + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/INSTALL.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/INSTALL.svn-base new file mode 100644 index 000000000..095b1eb40 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/INSTALL.svn-base @@ -0,0 +1,231 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PREFIX', the package will +use PREFIX as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..9b4c2eced --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,23 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +SUBDIRS = src . regressiontest include + +lib_LTLIBRARIES = libspatialindex.la libspatialindex_c.la + +libspatialindex_la_SOURCES = +libspatialindex_la_LIBADD = \ + src/spatialindex/liblibrary.la \ + src/storagemanager/libstoragemanager.la \ + src/rtree/librtree.la \ + src/mvrtree/libmvrtree.la \ + src/tprtree/libtprtree.la \ + src/tools/libtools.la + +libspatialindex_c_la_SOURCES = +libspatialindex_c_la_LIBADD = \ + libspatialindex.la \ + src/capi/libsidxc.la + +libspatialindex_la_LDFLAGS = -version-info 1:0:0 +libspatialindex_c_la_LDFLAGS = -version-info 1:0:0 -lstdc++ + +EXTRA_DIST = makefile.vc INSTALL.WIN spatialindex.sln spatialindex-vc/spatialindex.vcproj diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/NEWS.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/NEWS.svn-base new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/NEWS.svn-base diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/README.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/README.svn-base new file mode 100644 index 000000000..62f8132b8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/README.svn-base @@ -0,0 +1,423 @@ +***************************************************************************** + SpatialIndex Reference +***************************************************************************** + +:Author: Marios Hadjieleftheriou +:Contact: mhadji@gmail.com +:Revision: $Revision$ +:Date: $Date$ + +.. The next heading encountered becomes our H2 +.. + +.. sectnum:: + +.. contents:: + :depth: 2 + :backlinks: top + +------------------------------------------------------------------------------ +Introduction +------------------------------------------------------------------------------ + +You have downloaded the SpatialIndex Library. This is free software under LGPL. +The library is in beta testing stage. Use at your own risk. + +The purpose of this library is to provide: + 1. An extensible framework that will support robust spatial indexing + methods. + 2. Support for sophisticated spatial queries. Range, point location, + nearest neighbor and k-nearest neighbor as well as parametric + queries (defined by spatial constraints) should be easy to deploy and run. + 3. Easy to use interfaces for inserting, deleting and updating information. + 4. Wide variety of customization capabilities. Basic index and storage + characteristics like the page size, node capacity, minimum fan-out, + splitting algorithm, etc. should be easy to customize. + 5. Index persistence. Internal memory and external memory structures + should be supported. Clustered and non-clustered indices should + be easy to be persisted. + +------------------------------------------------------------------------------ +Installation +------------------------------------------------------------------------------ + +First run autogen.sh to generate the configure scripts. +By default include files and library files will be installed in /usr/local. If +you would like to use a different installation directory (e.g., in case +that you do not have root access) run the configure script with +the --prefix option: + +:: + + ./configure --prefix=/home/marioh/usr + +Make the library:: + + make + +Install the library:: + + make install + +------------------------------------------------------------------------------ +Using the Library +------------------------------------------------------------------------------ + +You are ready to use the library. All you have to +do is to include the file SpatialIndex.h in your source +files and then compile with the following options: + +:: + + g++ MyFile.cc -o MyFile -L/home/marioh/usr/lib -I/home/marioh/usr/include -lpthread -lspatialindex + +If the library is installed in the default /usr/local path, then the +-I and -L options are not necessary. + +If you are compiling on Mac OS X you will need to add the -bind_at_load +option when linking against the dynamic link libraries. OS X Tiger should +work out of the box, however, with XCode 3.0. + +------------------------------------------------------------------------------ +Library Overview +------------------------------------------------------------------------------ + +The library currently consists of six packages: + 1. The core spatialindex utilities. + 2. The storagemanager files. + 3. The spatialindex interfaces. + 4. The rtree index. + 5. The mvrtree index. + 6. The tprtree index. + +I will briefly present the basic features supported by each package. +For more details you will have to refer to the code, for now. + +Spatial Index Utilities +------------------------------------------------------------------------------ + +To provide common constructors and uniform initialization for all objects +provided by the library a PropertySet class is provided. A PropertySet +associates strings with Variants. Each property corresponds to one string. + +A basic implementation of a Variant is also provided that supports a +number of data types. The supported data types can be found in SpatialIndex.h + +PropertySet supports three functions: + + 1. getProperty returns the Variant associated with the given string. + 2. setProperty associates the given Variant with the given string. + 3. removeProperty removes the specified property from the PropertySet. + +A number of exceptions are also defined here. All exceptions extend +Exception and thus provide the what() method that returns a string +representation of the exception with useful comments. It is advisable to +use enclosing try/catch blocks when using any library objects. Many +constructors throw exceptions when invalid initialization properties are specified. + +A general IShape interface is defined. All shape classes should extend +IShape. Basic Region and Point classes are already provided. Please +check Region.h and Point.h for further details. + +Storage Manager +------------------------------------------------------------------------------ + +The library provides a common interface for storage management of all +indices. It consists of the IStorageManager interface, which provides functions +for storing and retrieving entities. An entity is viewed as a simple byte +array; hence it can be an index entry, a data entry or anything else that the +user wants to store. The storage manager interface is generic and does not apply +only to spatial indices. + +Classes that implement the IStorageManager interface decide on how to +store entities. simple main memory implementation is provided, for example, +that stores the entities using a vector, associating every entity with a +unique ID (the entry's index in the vector). A disk based storage manager +could choose to store the entities in a simple random access file, or a +database storage manager could store them in a relational table, etc. as long +as unique IDs are associated with every entity. Also, storage managers should +implement their own paging, compaction and deletion policies transparently +from the callers (be it an index or a user). + +The storeByteArray method gets a byte array and its length and an entity ID. +If the caller specifies NewPage as the input ID, the storage manager allocates +a new ID, stores the entity and returns the ID associated with the entity. +If, instead, the user specifies an already existing ID the storage manager +overwrites the old data. An exception is thrown if the caller requests +an invalid ID to be overwritten. + +The loadByteArray method gets an entity ID and returns the associated byte +array along with its length. If an invalid ID is requested, an exception is thrown. + +The deleteByteArray method removes the requested entity from storage. + +The storage managers should have no information about the types of entities +that are stored. There are three main reasons for this decision: + + 1. Any number of spatial indices can be stored in a single storage manager + (i.e. the same relational table, or binary file, or hash table, etc., can + be used to store many indices) using an arbitrary number of pages and + a unique index ID per index (this will be discussed shortly). + 2. Both clustered and non-clustered indices can be supported. A clustered + index stores the data associated with the entries that it contains along + with the spatial information that it indexes. A non-clustered index stores + only the spatial information of its entries. Any associated data are + stored separately and are associated with the index entries by a unique ID. + To support both types of indices, the storage manager interface should be + quite generic, allowing the index to decide how to store its data. + Otherwise clustered and non-clustered indices would have to be + implemented separately. + 3. Decision flexibility. For example, the users can choose a clustered index + that will take care of storing everything. They can choose a main memory + non-clustered index and store the actual data in MySQL. They can choose + a disk based non-clustered index and store the data manually in a + separate binary file or even in the same storage manager but doing a low + level customized data processing. + +Two storage managers are provided in the current implementation: + + 1) MemoryStorageManager + 2) DiskStorageManager + +MemoryStorageManager +~~~~~~~~~~~~~~~~~~~~~~~ + +As it is implied be the name, this is a main memory implementation. Everything +is stored in main memory using a simple vector. No properties are needed to +initialize a MemoryStorageManager object. When a MemoryStorageManager instance +goes out of scope, all data that it contains are lost. + +DiskStorageManager +~~~~~~~~~~~~~~~~~~~~~~~ + +The disk storage manager uses two random access files for storing information. +One with extension .idx and the other with extension .dat. + +A list of all the supported properties that can be provided during +initialization, follows: + +========= ======== =========================================================== +Property Type Description +========= ======== =========================================================== +FileName VT_PCHAR The base name of the file to open (no extension) +Overwrite VT_BOOL If Overwrite is true and a storage manager with the + specified filename already exists, it will be + truncated and overwritten. All data will be lost. +PageSize VT_ULONG The page size to use. If the specified filename + already exists and Overwrite is false, PageSize is ignored. +========= ======== =========================================================== + +For entities that are larger than the page size, multiple pages are used. +Although, the empty space on the last page is lost. Also, there is no effort +whatsoever to use as many sequential pages as possible. A future version +might support sequential I/O. Thus, real clustered indices cannot be supported yet. + +The purpose of the .idx file is to store vital information like the page size, +the next available page, a list of empty pages and the sequence of pages +associated with every entity ID. + +This class also provides a flush method that practically overwrites the +.idx file and syncs both file pointers. + +The .idx file is loaded into main memory during initialization and is +written to disk only after flushing the storage manager or during object +destruction. In case of an unexpected failure changes to the storage manager +will be lost due to a stale .idx file. Avoiding such disasters is future work. + +SpatialIndex Interfaces +------------------------------------------------------------------------------ + +A spatial index is any index structure that accesses spatial information +efficiently. It could range from a simple grid file to a complicated tree +structure. A spatial index indexes entries of type IEntry, which can be index +nodes, leaf nodes, data etc. depending on the structure characteristics. +The appropriate interfaces with useful accessor methods should be provided +for all types of entries. + +A spatial index should implement the ISpatialIndex interface. + +The containmentQuery method requires a query shape and a reference to a +valid IVisitor instance (described shortly). The intersectionQuery method +is the same. Both accept an IShape as the query. If the query shape is a simple +Region, than a classic range query is performed. The user though has the +ability to create her own shapes, thus defining her own intersection and +containment methods making possible to run any kind of range query without +having to modify the index. An example of a trapezoidal query is given in the +regressiontest directory. Have in mind that it is the users responsibility +to implement the correct intersection and containment methods between their +shape and the type of shapes that are stored by the specific index that they +are planning to use. For example, if an rtree index will be used, a trapezoid +should define intersection and containment between itself and Regions, since +all rtree nodes are of type Region. Hence, the user should have some knowledge +about the index internal representation, to run more sophisticated queries. + +A point location query is performed using the pointLocationQuery method. It +takes the query point and a visitor as arguments. + +Nearest neighbor queries can be performed with the nearestNeighborQuery method. +Its first argument is the number k of nearest neighbors requested. This +method also requires the query shape and a visitor object. The default +implementation uses the getMinimumDistance function of IShape for calculating +the distance of the query from the rectangular node and data entries stored +in the tree. A more sophisticated distance measure can be used by implementing +the INearestNeighborComparator interface and passing it as the last argument +of nearestNeighborQuery. For example, a comparator is necessary when the query +needs to be checked against the actual data stored in the tree, instead of +the rectangular data entry approximations stored in the leaves. + +For customizing queries the IVisitor interface (based on the Visitor +pattern [gamma94]) provides callback functions for visiting index and +leaf nodes, as well as data entries. Node and data information can be obtained +using the INode and IData interfaces (both extend IEntry). Examples of using +this interface include visualizing a query, counting the number of leaf +or index nodes visited for a specific query, throwing alerts when a +specific spatial region is accessed, etc. + +The queryStrategy method provides the ability to design more sophisticated +queries. It uses the IQueryStrategy interface as a callback that is called +continuously until no more entries are requested. It can be used to +implement custom query algorithms (based on the strategy pattern [gamma94]). + +A data entry can be inserted using the insertData method. The insertion +function will convert any shape into an internal representation depending on +the index. Every inserted object should be assigned an ID (called object +identifier) that will allow updating, deleting and reporting the object. +It is the responsibility of the caller to provide the index with IDs +(unique or not). Also, a byte array can be associated with an entry. The +byte arrays are stored along with the spatial information inside the leaf +nodes. Clustered indices can be supported in that way. The byte array can +also by null (in which case the length field should be zero), and no extra +space should be used per node. + +A data entry can be deleted using the deleteData method. The object shape +and ID should be provided. Spatial indices cluster objects according to +spatial characteristics and not IDs. Hence, the shape is essential for +locating and deleting an entry. + +Useful statistics are provided through the IStatistics interface and +the getStatistics method. + +Method getIndexProperties returns a PropertySet with all useful index +properties like dimensionality etc. + +A NodeCommand interface is provided for customizing Node operations. Using +the addWriteNodeCommand, addReadNodeCommand and addDeleteNodeCommand methods, +custom command objects are added in listener lists and get executed after +the corresponding operations. + +The isIndexValid method performs internal checks for testing the +integrity of a structure. It is used for debugging purposes. + +When a new index is created a unique index ID should be assigned to it, that +will be used when reloading the index from persistent storage. This index ID +should be returned as an IndexIdentifier property in the instance of the +PropsertySet that was used for constructing the index instance. Using +index IDs, multiple indices can be stored in the same storage manager. +It is the users responsibility to manager the index IDs. Associating the +wrong index ID with the wrong storage manager or index type has undefined +results. + +The RTree Package +------------------------------------------------------------------------------ + +The RTree index [guttman84] is a balanced tree structure that consists of +index nodes, leaf nodes and data. Every node (leaf and index) has a fixed +capacity of entries, (the node capacity) chosen at index creation An RTree +abstracts the data with their Minimum Bounding Region (MBR) and clusters +these MBRs according to various heuristics in the leaf nodes. Queries are +evaluated from the root of the tree down the leaves. Since the index is +balanced nodes can be under full. They cannot be empty though. A fill +factor specifies the minimum number of entries allowed in any node. The +fill factor is usually close to 70%. + +RTree creation involves: + + 1. Deciding if the index will be internal or external memory and selecting + the appropriate storage manager. + 2. Choosing the index and leaf capacity (also known as fan-out). + 3. Choosing the fill factor (from 1% to 99% of the node capacity). + 4. Choosing the dimensionality of the data. + 5. Choosing the insert/update policy (the RTree variant). + +If an already stored RTree is being reloaded for reuse, only the index ID +needs to be supplied during construction. In that case, some options cannot +be modified. These include: the index and leaf capacity, the fill factor and +the dimensionality. Note here, that the RTree variant can actually be +modified. The variant affects only when and how splitting occurs, and +thus can be changed at any time. + +An initialization PropertySet is used for setting the above options, +complying with the following property strings: + +========================== =========== ============================================================ +Property Type Description +========================== =========== ============================================================ +IndexIndentifier VT_LONG If specified an existing index will be + opened from the supplied storage manager with + the given index id. Behavior is unspecified + if the index id or the storage manager are incorrect. +Dimension VT_ULONG Dimensionality of the data that will be inserted. +IndexCapacity VT_ULONG The index node capacity. Default is 100. +LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. +FillFactor VT_DOUBLE The fill factor. Default is 70% +TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar +NearMinimumOverlapFactor VT_ULONG Default is 32. +SplitDistributionFactor VT_DOUBLE Default is 0.4 +ReinsertFactor VT_DOUBLE Default is 0.3 +EnsureTightMBRs VT_BOOL Default is true +IndexPoolCapacity VT_LONG Default is 100 +LeafPoolCapacity VT_LONG Default is 100 +RegionPoolCapacity VT_LONG Default is 1000 +PointPoolCapacity VT_LONG Default is 500 +========================== =========== ============================================================ + +Performance +------------------------------------------------------------------------------ + +Dataset size, data density, etc. have nothing to do with capacity and page +size. What you are trying to achieve is fast reads from the disk and take +advantage of disk buffering and prefetching. + +Normally, you select the page size to be equal to the disk page size (depends +on how you format the drive). Then you choose the node capacity to be enough +to fill the whole page (including data entries if you have any). + +There is a tradeoff though in making node capacity too large. The larger the +capacity, the longer the "for loops" for inserting, deleting, locating node +entries take (CPU time). On the other hand, the larger the capacity the +shorter the tree becomes, reducing the number of random IOs to reach the +leaves. Hence, you might want to fit multiple nodes (of smaller capacity) +inside a single page to balance I/O and CPU cost, in case your disk page size +is too large. + +Finally, if you have enough buffer space to fit most of the index nodes in +main memory, then large capacities do not make too much sense, because the +height of the tree does not matter any more. Of course, the smaller the +capacity, the larger the number of leaf nodes you will have to retrieve from +disk for range queries (point queries and nearest neighbor queries will not +suffer that much). So very small capacities hurt as well. + +There is another issue when trying to fit multiple nodes per page: Leftover +space. You might have leftover space due to data entries that do not have a +fixed size. Unfortunately, in that case, leftover space per page is lost, +negatively impacting space usage. + +Selecting the right page size is easy; make it equal to the disk page size. +Selecting the right node capacity is an art... + +------------------------------------------------------------------------------ +Contact Information +------------------------------------------------------------------------------ + +You can contact me at mhadji@gmail.com for further assistance. Please read the +above information carefully and also do not be afraid to browse through the +code and especially the test files inside regressiontest directory. + +------------------------------------------------------------------------------ +References +------------------------------------------------------------------------------ +[guttman84] "R-Trees: A Dynamic Index Structure for Spatial Searching" + Antonin Guttman, Proc. 1984 ACM-SIGMOD Conference on Management of Data (1985), 47-57. +[gamma94] "Design Patterns: Elements of Reusable Object-Oriented Software" + Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison Wesley. October 1994. + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/autogen.sh.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/autogen.sh.svn-base new file mode 100644 index 000000000..0c5823b7f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/autogen.sh.svn-base @@ -0,0 +1,42 @@ +#!/bin/sh +# $Id: autogen.sh 61 2007-12-11 20:13:48Z hobu $ +# +# Autotools boostrapping script +# +giveup() +{ + echo + echo " Something went wrong, giving up!" + echo + exit 1 +} + +OSTYPE=`uname -s` + +for libtoolize in glibtoolize libtoolize; do + LIBTOOLIZE=`which $libtoolize 2>/dev/null` + if test "$LIBTOOLIZE"; then + break; + fi +done + +#AMFLAGS="--add-missing --copy --force-missing" +AMFLAGS="--add-missing --copy" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal || giveup +#echo "Running autoheader" +#autoheader || giveup +echo "Running libtoolize" +$LIBTOOLIZE --force --copy || giveup +echo "Running automake" +automake $AMFLAGS # || giveup +echo "Running autoconf" +autoconf || giveup + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/configure.ac.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/configure.ac.svn-base new file mode 100644 index 000000000..dcf4e1cd1 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/configure.ac.svn-base @@ -0,0 +1,71 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) + +m4_define([sidx_version_major], [1]) +m4_define([sidx_version_minor], [6]) +m4_define([sidx_version_micro], [1]) +m4_define([sidx_version], + [sidx_version_major.sidx_version_minor.sidx_version_micro]) + +AC_INIT([spatialindex], [sidx_version], [mhadji@gmail.com], [spatialindex-src]) +AC_CANONICAL_BUILD + +debug_default="no" +CXXFLAGS="$CXXFLAGS" + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_LIBTOOL +AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects]) + +# Checks for header files. +AC_CHECK_HEADERS(fcntl.h,, [AC_MSG_ERROR([cannot find fcntl.h, bailing out])]) +AC_CHECK_HEADERS(unistd.h,, [AC_MSG_ERROR([cannot find unistd.h, bailing out])]) +AC_CHECK_HEADERS(sys/types.h,, [AC_MSG_ERROR([cannot find sys/types.h, bailing out])]) +AC_CHECK_HEADERS(sys/stat.h,, [AC_MSG_ERROR([cannot find sys/stat.h, bailing out])]) +AC_CHECK_HEADERS(pthread.h, [LIBS="$LIBS -lpthread"]) +AC_CHECK_HEADERS(sys/resource.h,, [AC_MSG_ERROR([cannot find sys/resource.h, bailing out])]) +AC_CHECK_HEADERS(sys/time.h,, [AC_MSG_ERROR([cannot find sys/time.h, bailing out])]) +AC_CHECK_HEADERS(stdint.h,, [AC_MSG_ERROR([cannot find stdint.h, bailing out])]) +#MH_CXX_HEADER_TOOLS + +LIBS="$LIBS" + +AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging [default=$debug_default]],, enable_debug=$debug_default) + +if test "x$enable_debug" = "xyes"; then + CXXFLAGS="$CXXFLAGS -g -DDEBUG" + AC_MSG_RESULT(checking wether debug information is enabled... yes) +else + CXXFLAGS="$CXXFLAGS -O2 -DNDEBUG" + AC_MSG_RESULT(checking wether debug information is enabled... no) +fi + +# Checks for library functions. +AC_CHECK_FUNCS([gettimeofday bzero memset memcpy bcopy]) + +AC_CONFIG_FILES([ Makefile + include/Makefile + include/capi/Makefile + include/tools/Makefile + src/Makefile + src/capi/Makefile + src/spatialindex/Makefile + src/storagemanager/Makefile + src/rtree/Makefile + src/mvrtree/Makefile + src/tprtree/Makefile + src/tools/Makefile + regressiontest/Makefile + regressiontest/rtree/Makefile + regressiontest/mvrtree/Makefile + regressiontest/tprtree/Makefile]) + +AC_OUTPUT + diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/depcomp.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/depcomp.svn-base new file mode 100644 index 000000000..11e2d3bfe --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/depcomp.svn-base @@ -0,0 +1,522 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to <bug-automake@gnu.org>. +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + elif test -f "$tmpdepfile2"; then + tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/install-sh.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/install-sh.svn-base new file mode 100644 index 000000000..dd97db7aa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/install-sh.svn-base @@ -0,0 +1,322 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-09-10.20 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/makefile.vc.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/makefile.vc.svn-base new file mode 100644 index 000000000..6d018a383 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/makefile.vc.svn-base @@ -0,0 +1,217 @@ + +.SUFFIXES: .cc + +SPATIALINDEX_HOME=c:\cvs\buildkit\spatialindex +DLL_VERSION = 1 + +BINDIR=$(SPATIALINDEX_HOME)\bin +OSGEO4W_DIR = $(SPATIALINDEX_HOME)\osgeo4w + + +############################################################################### +# Set BUILD_DEBUG balue to YES if you want to make debug build +# and to prepare not optimized binaries. +!IFNDEF BUILD_DEBUG +BUILD_DEBUG = NO +!ENDIF + + +############################################################################### +# Derive version of Visual C++ being used from NMAKE if not specified +# +# WARNING: +# If we should expect variety of NMAKE build versions, tests below may fail +# and we will need to fall back to setting MSVCVER as command line parameter. +# +!IF "$(_NMAKE_VER)" == "" +MSVCVER = 4.0 +!ERROR *** Failed to determine version of Visual C++ +!ELSEIF "$(_NMAKE_VER)" == "162" +MSVCVER = 5.0 +!ERROR *** Detected Visual C++ 5.0 - NOT SUPPORTED +!ELSEIF "$(_NMAKE_VER)" == "6.00.8168.0" +MSVCVER = 6.0 +!ERROR *** Detected Visual C++ 6.0 - NOT SUPPORTED +!ELSEIF "$(_NMAKE_VER)" == "7.00.9466" +MSVCVER = 7.0 +!ELSEIF "$(_NMAKE_VER)" == "7.10.3077" +MSVCVER = 7.1 +!ELSEIF "$(_NMAKE_VER)" == "8.00.50727.42" +MSVCVER = 8.0 +!ELSEIF "$(_NMAKE_VER)" == "8.00.50727.762" +MSVCVER = 8.0 +!ELSEIF "$(_NMAKE_VER)" == "9.00.21022.08" +MSVCVER = 9.0 +!ELSEIF "$(_NMAKE_VER)" == "9.00.30729.01" +MSVCVER = 9.0 +!ELSE +MSVCVER = 0.0 +!ENDIF + +!IF "$(MSVCVER)" == "0.0" +!MESSAGE *** Cannot determined Visual C++ version +!ERROR *** Aborting make job +!ELSE +!MESSAGE *** Using Microsoft NMAKE version $(_NMAKE_VER) +!MESSAGE *** Using Microsoft Visual C++ version $(MSVCVER) +!ENDIF + +############################################################################### +# Compilation flags for Release and Debug modes + +!IF "$(BUILD_DEBUG)" == "YES" +OPTFLAGS=/nologo /MDd /EHsc /Z7 /W4 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /DDEBUG /D_DEBUG /DDEBUG /Fd$(SPATIALINDEX_HOME)\spatialindex.pdb +LAS_LIB = spatialindex_d.lib +LAS_DLL = spatialindex_d$(DLL_VERSION).dll +LAS_LIB_DLL = spatialindex_i.lib +!ELSE + +# You may need to remove /GR if you are statically linking libLAS +OPTFLAGS=/nologo /MD /EHsc /Ox /GR /W2 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /DNDEBUG /D "PACKAGE_BUGREPORT=\"hobu.inc@gmail.com\"" /DSPATIALINDEX_CREATE_DLL=1 +LAS_LIB = spatialindex.lib +LAS_DLL = spatialindex$(DLL_VERSION).dll +CDLLNAME = spatialindex$(DLL_VERSION)_c.dll +CLIBNAME = spatialindex_c_i.lib +LAS_LIB_DLL = spatialindex_i.lib +!ENDIF + +# Check if multiple process build available +!IF "$(MSVCVER)" == "9.0" +MPFLAGS=/MP +!MESSAGE *** Using /MP flag with number of effective processors +!ELSE +MPFLAGS= +!ENDIF + +PACKAGE_VERSION=1.6.1 + +INCLUDES=-I$(SPATIALINDEX_HOME)/include -I$(SPATIALINDEX_HOME)/include/capi +CFLAGS= $(MPFLAGS) $(OPTFLAGS) $(INCLUDES) + + +# Commands +# +MAKE = nmake +RM = -del +CC= cl +LINK= link + +LAS_DIRLIST = src\mvrtree \ + src\rtree \ + src\spatialindex \ + src\storagemanager \ + src\tools \ + src\tprtree \ + src\capi + +OBJS = src\mvrtree\Index.obj \ + src\mvrtree\Leaf.obj \ + src\mvrtree\MVRtree.obj \ + src\mvrtree\Node.obj \ + src\mvrtree\Statistics.obj \ + src\rtree\BulkLoader.obj \ + src\rtree\Index.obj \ + src\rtree\Leaf.obj \ + src\rtree\Node.obj \ + src\rtree\RTree.obj \ + src\rtree\Statistics.obj \ + src\spatialindex\LineSegment.obj \ + src\spatialindex\MovingPoint.obj \ + src\spatialindex\MovingRegion.obj \ + src\spatialindex\Point.obj \ + src\spatialindex\Region.obj \ + src\spatialindex\SpatialIndexImpl.obj \ + src\spatialindex\TimePoint.obj \ + src\spatialindex\TimeRegion.obj \ + src\storagemanager\Buffer.obj \ + src\storagemanager\DiskStorageManager.obj \ + src\storagemanager\MemoryStorageManager.obj \ + src\storagemanager\RandomEvictionsBuffer.obj \ + src\tools\rand48.obj \ + src\tools\Tools.obj \ + src\tprtree\Index.obj \ + src\tprtree\Leaf.obj \ + src\tprtree\Node.obj \ + src\tprtree\Statistics.obj \ + src\tprtree\TPRTree.obj + +COBJS = src\capi\BoundsQuery.obj \ + src\capi\CountVisitor.obj \ + src\capi\CustomStorage.obj \ + src\capi\DataStream.obj \ + src\capi\Error.obj \ + src\capi\IdVisitor.obj \ + src\capi\Index.obj \ + src\capi\LeafQuery.obj \ + src\capi\ObjVisitor.obj \ + src\capi\sidx_api.obj\ + src\capi\Utility.obj + +default: $(LAS_DLL) $(CDLLNAME) + +all: default + + +$(LAS_LIB): $(OBJS) + if exist $(LAS_LIB) del $(LAS_LIB) + $(LINK) /lib /nologo /out:$(LAS_LIB) $(OBJS) + +$(LAS_DLL): $(LAS_LIB) $(RES) + $(LINK) /dll \ + $(OBJS) $(LAS_LIB) \ + /out:$(LAS_DLL) /implib:$(LAS_LIB_DLL) + if exist $(LAS_DLL).manifest mt -manifest $(LAS_DLL).manifest -outputresource:$(LAS_DLL);2 + +$(CDLLNAME): $(COBJS) $(LAS_DLL) + $(LINK) /dll /debug $(COBJS) $(LAS_LIB_DLL) /out:$(CDLLNAME) /implib:$(CLIBNAME) + if exist $(CDLLNAME).manifest mt -manifest $(CDLLNAME).manifest -outputresource:$(CDLLNAME);2 + + +install: default + -mkdir $(BINDIR) + -mkdir $(SPATIALINDEX_HOME)\packages + -mkdir $(BINDIR)\lib + -mkdir $(BINDIR)\include\spatialindex + -mkdir $(OSGEO4W_DIR) + -mkdir $(OSGEO4W_DIR)\lib + -mkdir $(OSGEO4W_DIR)\devel + -mkdir $(OSGEO4W_DIR)\lib\bin + -mkdir $(OSGEO4W_DIR)\devel\include + -mkdir $(OSGEO4W_DIR)\devel\include\spatialindex + -mkdir $(OSGEO4W_DIR)\devel\lib + xcopy /y /r /d /f spatialindex_i.lib $(BINDIR)\lib + xcopy /y /r /d /f spatialindex_i.lib $(OSGEO4W_DIR)\devel\lib + xcopy /y /r /d /f spatialindex.lib $(BINDIR)\lib + xcopy /y /r /d /f spatialindex.lib $(OSGEO4W_DIR)\devel\lib + xcopy /y /r /d /f /s include\* $(BINDIR)\include\spatialindex + xcopy /y /r /d /f /s include\* $(OSGEO4W_DIR)\devel\include\spatialindex + xcopy /y /r /d /f $(LAS_DLL) $(BINDIR) + xcopy /y /r /d /f $(LAS_DLL) $(OSGEO4W_DIR)\lib\bin + +.cc.obj: + $(CC) $(CFLAGS) /c $*.cc /Fo$@ + +.c.obj: + $(CC) $(CFLAGS) /c $*.c /Fo$@ + +clean: + $(RM) $(LAS_LIB) + $(RM) $(LAS_DLL) + $(RM) *.ilk + $(RM) *.manifest + $(RM) *.obj + $(RM) *.pdb + for %d in ( $(LAS_DIRLIST) ) do \ + del %d\*.obj + +package: install + cd $(SPATIALINDEX_HOME)/osgeo4w/lib + C:\cygwin\bin\tar.exe cvf ../../packages/libspatialindex-$(PACKAGE_VERSION).tar * + c:\cygwin\bin\bzip2.exe -f /cygdrive/c/cvs/buildkit/spatialindex/packages/libspatialindex-$(PACKAGE_VERSION).tar + cd $(SPATIALINDEX_HOME)/osgeo4w/ + cd $(SPATIALINDEX_HOME)/osgeo4w/devel + C:\cygwin\bin\tar.exe cvf ../../packages/libspatialindex-devel-$(PACKAGE_VERSION).tar * + c:\cygwin\bin\bzip2.exe -f /cygdrive/c/cvs/buildkit/spatialindex/packages/libspatialindex-devel-$(PACKAGE_VERSION).tar + cd $(SPATIALINDEX_HOME)/osgeo4w/ + cd $(SPATIALINDEX_HOME)/ + c:\cygwin\bin\zip.exe -r packages/libspatialindex-$(PACKAGE_VERSION)-win32.zip bin diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/missing.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/missing.svn-base new file mode 100644 index 000000000..64b5f901d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/missing.svn-base @@ -0,0 +1,353 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to <bug-automake@gnu.org>." + exit 0 + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit 0 + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/mkinstalldirs.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/mkinstalldirs.svn-base new file mode 100644 index 000000000..6fbe5e117 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/mkinstalldirs.svn-base @@ -0,0 +1,150 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2004-02-15.20 + +# Original author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to <bug-automake@gnu.org>." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit 0 + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/spatialindex.sln.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/spatialindex.sln.svn-base new file mode 100644 index 000000000..c0f1d6048 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/spatialindex.sln.svn-base @@ -0,0 +1,91 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spatialindex-vc", "spatialindex-vc\spatialindex.vcproj", "{38FBBD59-8344-4D8E-B728-3D51763B6A70}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeBulkLoad", "regressiontest\rtree\RTreeBulkLoad.vcproj", "{7D9C8655-0155-4EE3-B04C-6D831E2982CE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeGenerator", "regressiontest\rtree\RTreeGenerator.vcproj", "{03504DB7-ACF3-40CF-A8A7-310E80666DC0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeLoad", "regressiontest\rtree\RTreeLoad.vcproj", "{551D683C-E5DC-4713-9D9F-F629D15BE5DA}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeQuery", "regressiontest\rtree\RTreeQuery.vcproj", "{1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeExhaustive", "regressiontest\rtree\RTreeExhaustive.vcproj", "{D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.ActiveCfg = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.Build.0 = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.ActiveCfg = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.Build.0 = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.ActiveCfg = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.Build.0 = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.ActiveCfg = Release|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.Build.0 = Release|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|Win32.Build.0 = Debug|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|x64.ActiveCfg = Debug|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|x64.Build.0 = Debug|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|Win32.ActiveCfg = Release|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|Win32.Build.0 = Release|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|x64.ActiveCfg = Release|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|x64.Build.0 = Release|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|Win32.Build.0 = Debug|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|x64.ActiveCfg = Debug|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|x64.Build.0 = Debug|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|Win32.ActiveCfg = Release|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|Win32.Build.0 = Release|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|x64.ActiveCfg = Release|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|x64.Build.0 = Release|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|Win32.Build.0 = Debug|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|x64.ActiveCfg = Debug|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|x64.Build.0 = Debug|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|Win32.ActiveCfg = Release|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|Win32.Build.0 = Release|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|x64.ActiveCfg = Release|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|x64.Build.0 = Release|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|Win32.Build.0 = Debug|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|x64.ActiveCfg = Debug|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|x64.Build.0 = Debug|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|Win32.ActiveCfg = Release|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|Win32.Build.0 = Release|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|x64.ActiveCfg = Release|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|x64.Build.0 = Release|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|Win32.Build.0 = Debug|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|x64.ActiveCfg = Debug|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|x64.Build.0 = Debug|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|Win32.ActiveCfg = Release|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|Win32.Build.0 = Release|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|x64.ActiveCfg = Release|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/sci-libs/libspatialindex/svn/trunk/.svn/text-base/spatialindex.suo.svn-base b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/spatialindex.suo.svn-base Binary files differnew file mode 100644 index 000000000..040272d1d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/.svn/text-base/spatialindex.suo.svn-base diff --git a/sci-libs/libspatialindex/svn/trunk/AUTHORS b/sci-libs/libspatialindex/svn/trunk/AUTHORS new file mode 100644 index 000000000..c68fc7c6f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/AUTHORS @@ -0,0 +1,5 @@ +Marios Hadjieleftheriou -- Main author +mhadji@gmail.com + +Howard Butler -- minor packaging, Trac/SVN stuff, and some Windows work +hobu.inc@gmail.com
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/COPYING b/sci-libs/libspatialindex/svn/trunk/COPYING new file mode 100644 index 000000000..5ab7695ab --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/sci-libs/libspatialindex/svn/trunk/ChangeLog b/sci-libs/libspatialindex/svn/trunk/ChangeLog new file mode 100644 index 000000000..9e1c580d6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/ChangeLog @@ -0,0 +1,1206 @@ +2010-11-22 19:53 seang + + * src/capi/sidx_api.cc: Fix test of length value + +2010-11-22 19:23 hobu + + * src/capi/sidx_api.cc: whitespace normalization + +2010-11-22 19:00 seang + + * src/capi/sidx_api.cc: Add up deltas for multidimensional input + +2010-11-22 18:49 seang + + * src/capi/sidx_api.cc: Add up deltas for multidimensional input + +2010-11-22 18:46 hobu + + * src/capi/sidx_api.cc: revert r193 + +2010-11-22 16:02 hobu + + * src/capi/sidx_api.cc: we should set isPoint to true if we pass + our epsilon test -- this didn't work before + +2010-10-14 13:18 mhadji + + * include/tools/Tools.h, src/tools/Tools.cc: Removed + nextUnifromLongDouble. It was incorrect + +2010-10-13 15:10 mhadji + + * include/tools/Tools.h, src/tools/Tools.cc: Added + nextUniformLongDouble + +2010-09-16 13:56 hobu + + * Makefile.am: fix #25 and include visual studio files in the + release + +2010-09-16 13:53 hobu + + * makefile.vc: bump versions in preparation for release + +2010-09-16 13:52 hobu + + * configure.ac, include/Version.h: bump versions in preparation for + release + +2010-06-19 20:34 hobu + + * include/capi/CustomStorage.h, include/capi/Index.h, + include/capi/Makefile.am, include/capi/sidx_api.h, + include/capi/sidx_config.h, include/capi/sidx_impl.h, + makefile.vc, src/capi/CustomStorage.cc, src/capi/Index.cc, + src/capi/Makefile.am, src/capi/Utility.cc, src/capi/sidx_api.cc: + add Matthias' CustomStorage backend for C API + +2010-04-21 18:50 hobu + + * README: Add Marios' pagesize diatribe to the docs + +2010-04-12 19:56 hobu + + * ChangeLog: update ChangeLog + +2010-04-12 17:17 mhadji + + * regressiontest/rtree/Exhaustive.cc: + +2010-04-12 17:07 mhadji + + * regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/test3/run, spatialindex.suo, + src/rtree/BulkLoader.cc: Fixed rtree/BulkLoader infinit loop bug + +2010-03-31 15:33 hobu + + * src/capi/BoundsQuery.cc, src/capi/CountVisitor.cc, + src/capi/DataStream.cc, src/capi/IdVisitor.cc, src/capi/Index.cc, + src/capi/ObjVisitor.cc, src/capi/Utility.cc: format and layout + normalization + +2010-03-30 20:18 hobu + + * src/spatialindex/MovingRegion.cc: ensure that we instantiate the + ivOut with at least the ivIn so we have a properly constructed + Tools::Interval #16 + +2010-03-05 14:19 hobu + + * ., HOWTORELEASE.txt: add doc describing how to release + +2010-03-05 02:56 hobu + + * regressiontest/tprtree/test1, regressiontest/tprtree/test2: + propsets to ignore test output: + +2010-03-05 02:53 hobu + + * configure.ac: use subdir-objects for automake and rename the make + dist output to spatialindex-src + +2010-03-05 02:52 hobu + + * include/Version.h: increment version info in preparation for + release + +2010-03-05 01:59 hobu + + * ChangeLog: update for release + +2010-03-04 16:33 hobu + + * include/capi/CountVisitor.h, include/capi/Makefile.am, + include/capi/sidx_api.h, include/capi/sidx_impl.h, makefile.vc, + src/capi/CountVisitor.cc, src/capi/Makefile.am, + src/capi/sidx_api.cc: add CountVisitor to the CAPI to provide a + cumulation of the number of hits that land within a query + +2010-03-03 21:55 hobu + + * include/capi/IdVisitor.h, include/capi/ObjVisitor.h, + include/capi/sidx_api.h, regressiontest/rtree/test3/run, + src/capi/LeafQuery.cc, src/capi/sidx_api.cc: use uint64_t for + result counts instead of uint32_t in C API + +2009-12-29 02:35 hobu + + * regressiontest/mvrtree/Exhaustive.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/tprtree/Exhaustive.cc: fix up for gcc 4.4 + +2009-12-04 21:57 mhadji + + * spatialindex.suo, src/spatialindex/Region.cc: + +2009-12-04 18:46 mhadji + + * src/spatialindex/Region.cc: Fixed Region::touchesRegion member + function bug. + +2009-11-05 16:26 hobu + + * src/spatialindex/Region.cc: don't thrown an error when -DDEBUG is + on and we initialize an infinite Region + +2009-11-03 03:10 hobu + + * src/capi/sidx_api.cc: pass in a reference for the query bounds + +2009-11-03 03:04 hobu + + * src/capi/sidx_api.cc: try to do no harm when calling Index_Free + on something that's null + +2009-11-03 03:00 hobu + + * src/capi/sidx_api.cc: pass in a reference for the query bounds + +2009-11-03 02:15 hobu + + * src/capi/sidx_api.cc: copy the array using memcpy because we + can't free() something created with new + +2009-11-03 01:48 hobu + + * src/capi/sidx_api.cc: put the data in a newly malloc'd array to + match our std::free call of Index_Delete + +2009-11-02 21:32 hobu + + * src/capi/LeafQuery.cc: make sure to delete our shape when we're + done + +2009-11-02 21:32 hobu + + * src/capi/sidx_api.cc: get dimension from the Region, no need to + fetch from index properties + +2009-11-02 20:53 hobu + + * src/capi/sidx_api.cc: make sure we clean up the bounds and region + +2009-11-02 20:08 hobu + + * regressiontest/mvrtree/Generator.cc, + regressiontest/rtree/Generator.cc, + regressiontest/tprtree/Generator.cc, + regressiontest/tprtree/TPRTreeLoad.cc, + regressiontest/tprtree/TPRTreeQuery.cc, src/capi/sidx_api.cc, + src/mvrtree/Index.cc, src/mvrtree/MVRTree.cc, + src/mvrtree/Node.cc, src/rtree/Index.cc, src/rtree/Node.cc, + src/rtree/RTree.cc, src/spatialindex/LineSegment.cc, + src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, src/spatialindex/TimePoint.cc, + src/spatialindex/TimeRegion.cc, src/tools/Tools.cc, + src/tprtree/Index.cc, src/tprtree/Node.cc, + src/tprtree/TPRTree.cc: only #include <limits> where needed, and + not in the global Tools.h file + +2009-10-30 17:09 hobu + + * include/tools/Tools.h, regressiontest/mvrtree/Exhaustive.cc, + regressiontest/mvrtree/Generator.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/Generator.cc, + regressiontest/tprtree/Generator.cc, src/mvrtree/Node.cc, + src/rtree/BulkLoader.cc, src/rtree/Node.cc, src/rtree/RTree.cc, + src/spatialindex/LineSegment.cc, src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, + src/storagemanager/RandomEvictionsBuffer.cc, src/tprtree/Node.cc: + remove <cmath> <limits> and <climits> from Tools.h and include + them seperately in each file that needs them + +2009-10-30 16:37 hobu + + * include/capi/sidx_api.h: define to denote we're C API + +2009-10-30 15:03 hobu + + * include/capi/sidx_config.h: add a newline + +2009-10-22 02:42 hobu + + * src/capi/sidx_api.cc: make sure we use new/delete instead of + new/free + +2009-10-21 17:35 hobu + + * ., include/LineSegment.h, include/Point.h, include/Region.h, + include/SpatialIndex.h, include/capi, src/capi, + src/spatialindex/LineSegment.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc: remove namespace pollution of Tools:: + into the globally include'd header SpatialIndex.h + +2009-10-20 15:24 hobu + + * configure.ac, makefile.vc: bump versions in preparation for + release + +2009-10-19 20:31 hobu + + * include/capi/sidx_api.h: add SIDX_Version prototype + +2009-10-19 20:23 hobu + + * ltmain.sh: ltmain.sh doesn't belong in svn + +2009-10-19 20:23 hobu + + * include/capi/Makefile.in, src/capi/Makefile.in: Makefile.in's + don't belong in svn + +2009-10-19 18:50 hobu + + * makefile.vc: C API compilation fix + +2009-10-19 18:50 hobu + + * src/tools/Tools.cc: tmpname fixes so we compile on msvc2003 + +2009-10-19 18:29 hobu + + * makefile.vc: don't define a variable to "" or cl will complain + +2009-10-08 19:32 hobu + + * src/rtree/BulkLoader.cc: bleaf and bindex switched around in + createLevel call + +2009-09-17 20:40 hobu + + * include/capi/LeafQuery.h, include/capi/sidx_api.h, + src/capi/LeafQuery.cc, src/capi/sidx_api.cc: more leaf querying + code + +2009-09-16 18:45 hobu + + * include/capi/LeafQuery.h, include/capi/Makefile.am, + include/capi/Makefile.in, include/capi/sidx_impl.h, + src/capi/LeafQuery.cc, src/capi/Makefile.am, + src/capi/Makefile.in, src/capi/sidx_api.cc: add beginnings of + leaf querying to C API + +2009-09-16 03:34 hobu + + * include/capi/Item.h, include/capi/ObjVisitor.h, + include/capi/sidx_config.h, include/capi/sidx_impl.h, + src/capi/Item.cc, src/capi/Makefile.am, src/capi/Makefile.in, + src/capi/ObjVisitor.cc, src/capi/sidx_api.cc: remove the + duplicate and unnecessary Item construct that was masking the + already existing IData interface + +2009-08-31 15:32 hobu + + * makefile.vc: support building the c api + +2009-08-24 13:25 hobu + + * regressiontest/mvrtree/Exhaustive.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/tprtree/Exhaustive.cc: fix issue with uint32_t by + copying macros from Tools.h + +2009-08-19 20:47 hobu + + * Makefile.am: try to ensure -lstdc++ is linked + +2009-08-19 19:56 hobu + + * include/capi, src/capi: ignores + +2009-08-19 16:37 hobu + + * Makefile.am, configure.ac, include/Makefile.am, include/capi, + include/capi/BoundsQuery.h, include/capi/DataStream.h, + include/capi/Error.h, include/capi/IdVisitor.h, + include/capi/Index.h, include/capi/Item.h, + include/capi/Makefile.am, include/capi/Makefile.in, + include/capi/ObjVisitor.h, include/capi/Utility.h, + include/capi/sidx_api.h, include/capi/sidx_config.h, + include/capi/sidx_impl.h, include/tools/Makefile.am, + src/Makefile.am, src/capi, src/capi/BoundsQuery.cc, + src/capi/DataStream.cc, src/capi/Error.cc, src/capi/IdVisitor.cc, + src/capi/Index.cc, src/capi/Item.cc, src/capi/Makefile.am, + src/capi/Makefile.in, src/capi/ObjVisitor.cc, + src/capi/Utility.cc, src/capi/sidx_api.cc: add C API (not + currently built on windows) + +2009-08-19 15:25 hobu + + * .: ignore propset + +2009-08-19 15:24 hobu + + * regressiontest/mvrtree/test1, regressiontest/mvrtree/test2, + regressiontest/rtree, regressiontest/rtree/test1, + regressiontest/rtree/test2, regressiontest/rtree/test3, + regressiontest/rtree/test4, regressiontest/tprtree/test1, + regressiontest/tprtree/test2: propsets to ignore test results + +2009-08-18 18:07 hobu + + * include/tools/Tools.h, src/tools/Tools.cc: locking for + Tools::PropertySet (commented out though because it doesn't work + +2009-08-14 17:41 hobu + + * src/tools/Tools.cc: comment out PropertySet locking for now + +2009-08-14 15:19 hobu + + * include/tools/Tools.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/rtree/RTree.cc, src/rtree/RTree.h, + src/tools/Tools.cc, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: use HAVE_PTHREAD_H for #ifdef, make + Tools::PropertySet threadsafe for read/write + +2009-08-13 19:10 mhadji + + * spatialindex.suo, src/rtree/BulkLoader.cc, + src/rtree/BulkLoader.h, src/rtree/RTree.cc: + +2009-08-13 15:42 mhadji + + * spatialindex-vc/spatialindex.vcproj, spatialindex.suo: + +2009-08-13 15:24 mhadji + + * include/LineSegment.h, include/MVRTree.h, include/MovingPoint.h, + include/MovingRegion.h, include/Point.h, include/RTree.h, + include/Region.h, include/SpatialIndex.h, include/TPRTree.h, + include/TimePoint.h, include/TimeRegion.h, + include/tools/PointerPool.h, include/tools/Tools.h, + regressiontest/rtree/RTreeBulkLoad.cc, + regressiontest/rtree/RTreeQuery.cc, + regressiontest/rtree/test1/run, regressiontest/rtree/test2/run, + spatialindex.suo, src/mvrtree/Index.cc, src/mvrtree/Index.h, + src/mvrtree/Leaf.cc, src/mvrtree/Leaf.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/mvrtree/PointerPoolNode.h, src/mvrtree/Statistics.cc, + src/mvrtree/Statistics.h, src/rtree/BulkLoader.cc, + src/rtree/BulkLoader.h, src/rtree/Index.cc, src/rtree/Index.h, + src/rtree/Leaf.cc, src/rtree/Leaf.h, src/rtree/Node.cc, + src/rtree/Node.h, src/rtree/PointerPoolNode.h, + src/rtree/RTree.cc, src/rtree/RTree.h, src/rtree/Statistics.cc, + src/rtree/Statistics.h, src/spatialindex/LineSegment.cc, + src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, src/spatialindex/TimePoint.cc, + src/spatialindex/TimeRegion.cc, src/storagemanager/Buffer.cc, + src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, + src/storagemanager/RandomEvictionsBuffer.cc, src/tools/Tools.cc, + src/tprtree/Index.cc, src/tprtree/Index.h, src/tprtree/Leaf.cc, + src/tprtree/Leaf.h, src/tprtree/Node.cc, src/tprtree/Node.h, + src/tprtree/PointerPoolNode.h, src/tprtree/Statistics.cc, + src/tprtree/Statistics.h, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: 1. Replace size_t with uint32_t to fix + 64/32 bit compatibility issues + 2. Fixed memory bug related to data array and bulk loading for + RTree. + +2009-08-10 13:35 hobu + + * include/SpatialIndex.h, include/tools/Tools.h: remove #define + interface, use class + +2009-08-06 01:11 hobu + + * makefile.vc: osgeo4w packaging + +2009-08-05 20:21 hobu + + * include/tools/Tools.h: don't redefine interface if it is already + defined (/me scowls at windows + +2009-08-05 19:27 hobu + + * src/rtree/BulkLoader.cc: comment out record deletion entirely + +2009-08-05 17:58 hobu + + * src/rtree/BulkLoader.cc: guard against invalid delete + +2009-07-30 18:48 hobu + + * Makefile.am, configure.ac: bump version to 1.4.0 in prep for + release, add a windows docs to the dist + +2009-07-30 16:57 hobu + + * src/storagemanager/DiskStorageManager.cc: Add a + CheckFilesExists(Tools::PropertySet&) method instead of the cheap + way we were checking for existence before. This takes into + account the file extensions and only returns true if both files + exist + +2009-07-30 16:56 hobu + + * include/tools/Tools.h: move the warning about 4251 down into + _MSC_VER + +2009-07-30 03:10 hobu + + * ChangeLog, configure.ac: new changelog + +2009-07-30 02:32 hobu + + * makefile.vc: update for new layout. make sure to build dll + appropriately + +2009-07-29 21:24 hobu + + * include/tools/Tools.h: turn off warning 4251 + +2009-07-29 20:57 hobu + + * include/Makefile.am, include/SpatialIndex.h, include/Version.h: + fix #15 and provide a way to determine the library version at + compile time + +2009-07-29 20:50 hobu + + * makefile.vc: add back makefile.vc + +2009-07-22 19:29 hobu + + * src/spatialindex/Region.cc: a note about the debugging lint that + is incorrect when the bounds are infinity + +2009-07-22 19:24 hobu + + * regressiontest/rtree/Exhaustive.cc: make sure to #include + <cstring> to satisfy gcc 4.3+ + +2009-07-22 15:23 mhadji + + * regressiontest/rtree/RTreeBulkLoad.vcproj, + regressiontest/rtree/RTreeExhaustive.vcproj, + regressiontest/rtree/RTreeGenerator.vcproj, + regressiontest/rtree/RTreeLoad.vcproj, + regressiontest/rtree/RTreeQuery.vcproj, + spatialindex-vc/spatialindex.vcproj, spatialindex.suo: + +2009-07-22 15:18 mhadji + + * spatialindex.sln, spatialindex.suo: + +2009-07-21 13:11 mhadji + + * src/tools/Tools.cc: + +2009-07-20 20:32 hobu + + * src/storagemanager/DiskStorageManager.cc: attempt to fix #8 and + allow users to specify extensions for the dat and idx files of + the diskstorage manager + +2009-07-20 17:35 hobu + + * src/tools/Tools.cc: make sure to update existing values in + setProperties instead of assuming it doesn't exist in the map + +2009-07-20 15:01 mhadji + + * spatialindex.suo, src/mvrtree/MVRTree.cc, src/rtree/RTree.cc, + src/tprtree/TPRTree.cc: + +2009-07-19 14:51 mhadji + + * include/LineSegment.h, include/MVRTree.h, include/MovingPoint.h, + include/MovingRegion.h, include/Point.h, include/RTree.h, + include/Region.h, include/SpatialIndex.h, include/TPRTree.h, + include/TimePoint.h, include/TimeRegion.h, include/tools/Tools.h, + spatialindex.suo: + +2009-07-19 01:26 mhadji + + * INSTALL.WIN: + +2009-07-19 01:15 mhadji + + * spatialindex-vc/spatialindex.vcproj, spatialindex.suo: + +2009-07-19 01:13 mhadji + + * spatialindex.suo: + +2009-07-19 01:09 mhadji + + * makefile.vc, regressiontest/rtree/RTreeBulkLoad.vcproj, + spatialindex.suo: + +2009-07-19 01:02 mhadji + + * INSTALL.WIN, regressiontest/rtree/RTreeBulkLoad.vcproj, + regressiontest/rtree/RTreeExhaustive.vcproj, + regressiontest/rtree/RTreeGenerator.vcproj, + regressiontest/rtree/RTreeLoad.vcproj, + regressiontest/rtree/RTreeQuery.vcproj, + regressiontest/rtree/test3/run, + spatialindex-vc/spatialindex.vcproj, spatialindex.sln, + spatialindex.suo: + +2009-07-18 22:52 mhadji + + * include/SpatialIndex.h, include/tools/Tools.h: + +2009-07-18 22:19 mhadji + + * spatialindex-vc/spatialindex.vcproj.RESEARCH.marioh.user: + +2009-07-18 22:19 mhadji + + * include/LineSegment.h, include/MVRTree.h, include/MovingPoint.h, + include/MovingRegion.h, include/Point.h, include/RTree.h, + include/Region.h, include/SpatialIndex.h, include/TPRTree.h, + include/TimePoint.h, include/TimeRegion.h, + include/tools/Makefile.am, include/tools/PointerPool.h, + include/tools/PoolPointer.h, include/tools/SmartPointer.h, + include/tools/TemporaryFile.h, include/tools/Tools.h, + include/tools/rand48.h, makefile.vc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/Generator.cc, + regressiontest/rtree/RTreeBulkLoad.cc, + regressiontest/rtree/RTreeBulkLoad.vcproj, + regressiontest/rtree/RTreeExhaustive.vcproj, + regressiontest/rtree/RTreeGenerator.vcproj, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeLoad.vcproj, + regressiontest/rtree/RTreeQuery.vcproj, + regressiontest/rtree/test3/run, spatialindex-vc, + spatialindex-vc/spatialindex.vcproj, + spatialindex-vc/spatialindex.vcproj.RESEARCH.marioh.user, + src/mvrtree/Index.cc, src/mvrtree/Index.h, src/mvrtree/Leaf.cc, + src/mvrtree/Leaf.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/mvrtree/PointerPoolNode.h, src/mvrtree/Statistics.h, + src/rtree/BulkLoader.cc, src/rtree/BulkLoader.h, + src/rtree/Index.h, src/rtree/Leaf.h, src/rtree/Node.h, + src/rtree/PointerPoolNode.h, src/rtree/RTree.cc, + src/rtree/RTree.h, src/rtree/Statistics.h, + src/spatialindex/MovingRegion.cc, + src/spatialindex/SpatialIndexImpl.cc, + src/spatialindex/SpatialIndexImpl.h, + src/storagemanager/Buffer.cc, src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, + src/storagemanager/RandomEvictionsBuffer.cc, + src/storagemanager/RandomEvictionsBuffer.h, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/Makefile.am, src/tools/TemporaryFile.cc, + src/tools/Tools.cc, src/tprtree/Index.h, src/tprtree/Leaf.h, + src/tprtree/Node.h, src/tprtree/PointerPoolNode.h, + src/tprtree/Statistics.h, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: + +2009-07-15 14:39 hobu + + * include/SpatialIndex.h, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/rtree/Node.cc, src/rtree/Node.h, src/rtree/RTree.cc, + src/rtree/RTree.h, src/tprtree/Node.cc, src/tprtree/Node.h: apply + Willem's patch for #14 + +2009-07-06 22:23 hobu + + * src/rtree/RTree.cc: more descriptive and separate exception + descriptions for FillFactor inconsistencies + +2009-07-06 14:38 hobu + + * include/SpatialIndex.h, ltmain.sh: silence warnings about windows + compiler complaints on non-windows systems + +2009-05-28 17:52 hobu + + * makefile.vc: rename dlls to not have lib* in front of them + +2009-05-28 16:31 hobu + + * makefile.vc: A much improved windows makefile based in libLAS' + +2009-05-28 16:31 hobu + + * include/SpatialIndex.h: On MSVC, just about every class complains + about 4250, inheritance by dominance. We'll just shut that up for + now. + +2009-05-14 18:26 hobu + + * src/tools/TemporaryFile.cc: apply Patrick Mézard's patch for the + inverted use of mktemp on windows #13 + +2009-05-14 18:21 hobu + + * src/tools/Tools.cc: Fix #12, add time.h so msvc9 works + +2009-05-04 17:10 hobu + + * regressiontest/mvrtree/Exhaustive.cc, + regressiontest/mvrtree/MVRTreeLoad.cc, + regressiontest/mvrtree/MVRTreeQuery.cc, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeQuery.cc, + regressiontest/tprtree/Generator.cc, src/mvrtree/MVRTree.cc, + src/mvrtree/Node.cc, src/rtree/BulkLoader.cc, src/rtree/Leaf.cc, + src/rtree/Node.cc, src/rtree/RTree.cc, + src/spatialindex/LineSegment.cc, src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, src/spatialindex/Point.cc, + src/spatialindex/Region.cc, src/spatialindex/TimePoint.cc, + src/spatialindex/TimeRegion.cc, src/storagemanager/Buffer.cc, + src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, src/tools/Tools.cc, + src/tprtree/Leaf.cc, src/tprtree/Node.cc, src/tprtree/TPRTree.cc: + apply the patch for #11 - cstring and limits includes so gcc 4.3+ + works + +2008-05-30 19:42 mhadji + + * src/tools/Makefile.am, src/tools/Tools.cc: + +2008-05-23 18:27 mhadji + + * makefile.vc: + +2008-05-23 17:55 mhadji + + * configure.ac: + +2008-05-23 17:28 mhadji + + * regressiontest/rtree/RTreeLoad.cc, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h: + +2008-05-18 12:35 mhadji + + * ltmain.sh: + +2008-04-30 05:39 hobu + + * .: propset to ignore aclocal.m4 + +2008-04-30 05:39 hobu + + * aclocal.m4: aclocal.m4 is autogenerated. removing + +2008-04-30 05:35 hobu + + * ., include, include/tools, regressiontest, + regressiontest/mvrtree, regressiontest/rtree, + regressiontest/tprtree, src, src/mvrtree, src/rtree, + src/spatialindex, src/storagemanager, src/tools, src/tprtree: set + svn:ignore properties for autogenerated files and automake cruft + +2008-04-30 05:27 hobu + + * Makefile.in, include/Makefile.in, include/tools/Makefile.in, + regressiontest/Makefile.in, regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, src/Makefile.in, + src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tools/Makefile.in, src/tprtree/Makefile.in: delete + Makefile.in's from source tree. Use autogen.sh to remake them if + building from svn source yourself + +2008-04-30 05:26 hobu + + * include/tools/Makefile.am: add rand48.h to dist target + +2008-04-29 19:47 mhadji + + * regressiontest/rtree/test1/data, + regressiontest/rtree/test1/queries: + +2008-04-29 18:17 mhadji + + * include/tools/rand48.hpp: + +2008-04-29 18:06 mhadji + + * include/tools/rand48.h: + +2008-04-29 18:03 mhadji + + * INSTALL, Makefile.in, aclocal.m4, configure.ac, mkinstalldirs, + regressiontest/Makefile.in, regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/TemporaryFile.cc, src/tools/Tools.cc: + +2008-04-29 16:36 mhadji + + * makefile.vc: + +2008-04-29 16:36 mhadji + + * include/Makefile.in, include/SpatialIndex.h, + include/tools/Makefile.in, include/tools/Tools.h: + +2008-04-29 16:36 mhadji + + * src/Makefile.in, src/mvrtree/Makefile.in, src/mvrtree/Node.cc, + src/rtree/Makefile.in, src/spatialindex/LineSegment.cc, + src/spatialindex/Makefile.in, src/spatialindex/MovingRegion.cc, + src/storagemanager/Makefile.in, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/Makefile.in, src/tprtree/Makefile.in: + +2008-04-29 15:40 mhadji + + * src/spatialindex/MovingRegion.cc: Fixex malloc memory leak. + +2008-04-29 15:40 mhadji + + * src/spatialindex/LineSegment.cc: Fixed malloc memory leak + +2008-02-26 16:15 hobu + + * src/tools/rand48.cc: oops. Add missing file + +2008-02-26 16:14 hobu + + * include/tools/rand48.hpp: oops. Add missing file + +2008-01-25 19:43 hobu + + * include/MVRTree.h, include/RTree.h, include/SpatialIndex.h, + include/TPRTree.h, include/tools/Tools.h, makefile.vc, + src/mvrtree/Index.cc, src/mvrtree/Leaf.cc, src/mvrtree/Node.cc, + src/rtree/BulkLoader.cc, src/rtree/Index.cc, src/rtree/Leaf.cc, + src/rtree/Node.cc, src/spatialindex/LineSegment.cc, + src/spatialindex/MovingRegion.cc, src/storagemanager/Buffer.cc, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/TemporaryFile.cc, src/tools/Tools.cc, + src/tprtree/Index.cc, src/tprtree/Leaf.cc, src/tprtree/Node.cc: + Initial push of windows patches + +2008-01-23 16:25 mhadji + + * INSTALL: + +2008-01-21 14:19 mhadji + + * README, regressiontest/rtree/test3/run: + +2008-01-19 20:51 hobu + + * configure.ac, makefile.vc: bump version to 1.3 + +2008-01-19 18:42 hobu + + * ChangeLog: Add an auto-generated ChangeLog + +2008-01-19 18:37 hobu + + * AUTHORS: add myself and some notes + +2008-01-19 18:36 hobu + + * INSTALL: update to ReST + +2008-01-19 18:09 hobu + + * README: update ReST + +2008-01-19 18:09 hobu + + * README: update ReST + +2008-01-19 18:03 hobu + + * README: update ReST + +2008-01-19 18:02 hobu + + * README: update ReST + +2008-01-19 18:02 hobu + + * README: update ReST + +2008-01-19 18:01 hobu + + * README: update ReST + +2008-01-19 17:59 hobu + + * README: update ReST + +2008-01-19 17:59 hobu + + * README: update ReST + +2008-01-19 17:58 hobu + + * README: update ReST + +2008-01-19 17:58 hobu + + * README: update ReST + +2008-01-19 17:56 hobu + + * README: update ReST + +2008-01-19 17:55 hobu + + * README: update ReST + +2008-01-19 17:29 hobu + + * README: update ReST + +2008-01-19 17:26 hobu + + * README: update to ReST + +2008-01-19 17:02 hobu + + * README: set mimetype to reStructured text so Trac will render it + for us in the browser + +2008-01-17 23:34 hobu + + * regressiontest/tprtree/Makefile.am, + regressiontest/tprtree/Makefile.in, src/mvrtree/Makefile.am, + src/mvrtree/Makefile.in, src/rtree/Makefile.am, + src/rtree/Makefile.in, src/spatialindex/Makefile.am, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.am, + src/storagemanager/Makefile.in, src/tprtree/Makefile.am, + src/tprtree/Makefile.in: add internal headers to the _SOURCES + targets so they get included in make dist + +2008-01-17 17:06 hobu + + * Makefile.in, aclocal.m4, autogen.sh, include/Makefile.in, + include/tools/Makefile.in, ltmain.sh, regressiontest/Makefile.in, + regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, src/Makefile.in, + src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tools/Makefile.in, src/tprtree/Makefile.in: add autogen.sh to + simplify auto stuff + +2008-01-17 17:04 hobu + + * debian: move debian packaging stuff out of trunk + +2008-01-15 19:33 hobu + + * makefile.vc: add nmake makefile + +2007-12-07 20:44 kenneth + + * debian/libspatialindex1.dirs, debian/libspatialindex1.install, + debian/libspatialindex11.dirs, debian/libspatialindex11.install: + Wrong names + +2007-12-07 19:58 kenneth + + * configure, debian/rules: Fixed rules file + +2007-12-07 18:10 kenneth + + * config.guess, config.sub, debian/control: Updates to the control + file (packaging) + Removal of files that shouldn't be in SVN + +2007-11-30 18:04 mhadji + + * Makefile.in, configure, configure.ac: + +2007-11-30 16:50 seang + + * Makefile.am: Version info to 1:0:0 + +2007-11-29 22:26 mhadji + + * INSTALL, configure, configure.ac: + +2007-11-29 21:54 mhadji + + * include/LineSegment.h, include/Point.h, include/Region.h, + include/tools/LineSegment.h, include/tools/Point.h, + include/tools/Region.h, src/spatialindex/LineSegment.cc, + src/spatialindex/Point.cc, src/spatialindex/Region.cc, + src/tools/ExternalSort.cc, src/tools/ExternalSort.h, + src/tools/TemporaryFile.cc, src/tools/Tools.cc: + +2007-11-29 21:48 mhadji + + * Makefile.am, Makefile.in, aclocal.m4, configure, configure.ac, + include/Makefile.am, include/Makefile.in, include/MovingPoint.h, + include/MovingRegion.h, include/SpatialIndex.h, + include/TimePoint.h, include/TimeRegion.h, + include/tools/Makefile.am, include/tools/Makefile.in, + include/tools/PointerPool.h, include/tools/PoolPointer.h, + include/tools/SmartPointer.h, include/tools/TemporaryFile.h, + include/tools/Tools.h, regressiontest/Makefile.in, + regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Generator.cc, + regressiontest/tprtree/Makefile.in, + regressiontest/tprtree/RandomGenerator.cc, + regressiontest/tprtree/RandomGenerator.h, src/Makefile.in, + src/mvrtree/Index.cc, src/mvrtree/Leaf.cc, + src/mvrtree/MVRTree.cc, src/mvrtree/Makefile.in, + src/mvrtree/Node.cc, src/mvrtree/Statistics.cc, + src/rtree/BulkLoader.cc, src/rtree/Index.cc, src/rtree/Leaf.cc, + src/rtree/Makefile.in, src/rtree/Node.cc, src/rtree/RTree.cc, + src/rtree/Statistics.cc, src/spatialindex/Makefile.am, + src/spatialindex/Makefile.in, src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, + src/spatialindex/SpatialIndexImpl.h, + src/spatialindex/TimePoint.cc, src/spatialindex/TimeRegion.cc, + src/storagemanager/Buffer.cc, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/Makefile.in, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/RandomEvictionsBuffer.cc, + src/tools/Makefile.am, src/tools/Makefile.in, src/tools/geometry, + src/tools/tools, src/tprtree/Index.cc, src/tprtree/Leaf.cc, + src/tprtree/Makefile.in, src/tprtree/Node.cc, + src/tprtree/Statistics.cc, src/tprtree/TPRTree.cc: + +2007-11-29 18:00 seang + + * debian, debian/README, debian/README.Debian, debian/changelog, + debian/compat, debian/control, debian/copyright, debian/dirs, + debian/docs, debian/libspatialindex1-dev.dirs, + debian/libspatialindex1-dev.install, + debian/libspatialindex1.doc-base.EX, + debian/libspatialindex11.dirs, debian/libspatialindex11.install, + debian/rules: Add debian directory created by dh_make + +2007-11-29 04:05 hobu + + * Makefile.am, Makefile.in: use -version-info instead of -release + +2007-11-29 00:59 hobu + + * include/Makefile.in, include/tools/Makefile.in: include + Makefile.in's + +2007-11-29 00:55 hobu + + * Makefile.am, Makefile.in: use .'s to separate version info and + don't do -no-undefined + +2007-11-29 00:19 hobu + + * Makefile.am: tweak formatting + +2007-11-29 00:11 seang + + * Makefile.am: Add version-info to Makefile.am + +2007-11-28 23:54 hobu + + * Makefile.am, Makefile.in, include/Makefile.am, + include/tools/Makefile.am: finish incorporating -ltools + +2007-11-28 22:48 hobu + + * Makefile.am, Makefile.in, configure, configure.ac, + include/Makefile.am, include/tools/Makefile.am: more progress on + automake for includes directories... close, but not quite + +2007-11-28 22:38 hobu + + * include/Makefile.am, include/tools/Makefile.am: Add automake + files for includes + +2007-11-28 21:03 hobu + + * Makefile.am, Makefile.in, aclocal.m4, configure, configure.ac, + include/tools, regressiontest/Makefile.in, + regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/tprtree/Makefile.in, src/Makefile.am, + src/Makefile.in, src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tools, src/tools/Makefile.in, src/tools/geometry/Makefile.am, + src/tools/geometry/Makefile.in, src/tools/tools/Makefile.am, + src/tools/tools/Makefile.in, src/tprtree/Makefile.in: start + incorporating -ltools into the tree + +2007-08-30 15:16 mhadji + + * INSTALL, a: README should be INSTALL, and INSTALL should be + README + +2007-08-30 15:15 mhadji + + * INSTALL, README: README should be INSTALL, and INSTALL should be + README + +2007-08-30 15:13 mhadji + + * README, a: README file should be INSTALL, and INSTALL should be + README + +2007-08-02 04:37 hobu + + * src/storagemanager/DiskStorageManager.cc: revert r9 + +2007-08-02 04:37 hobu + + * src/rtree/Leaf.cc: revert r10 + +2007-08-02 04:36 hobu + + * src/rtree/Node.cc: revert r11 + +2007-08-02 04:36 hobu + + * src/rtree/RTree.cc: revert r12 + +2007-08-02 04:35 hobu + + * src/mvrtree/MVRTree.cc: revert r13 + +2007-08-02 04:34 hobu + + * src/spatialindex/SpatialIndexImpl.h: add strings.h + +2007-08-02 04:27 hobu + + * src/mvrtree/MVRTree.cc: add strings.h + +2007-08-02 04:26 hobu + + * src/rtree/RTree.cc: add strings.h + +2007-08-02 04:25 hobu + + * src/rtree/Node.cc: add strings.h + +2007-08-02 02:23 hobu + + * src/rtree/Leaf.cc: include <strings.h> + +2007-08-02 02:21 hobu + + * src/storagemanager/DiskStorageManager.cc: include <strings.h> in + DiskStorageManager (this is not available on Solaris by default) + +2007-08-01 20:49 hobu + + * regressiontest/rtree/test1/data, + regressiontest/rtree/test1/queries: add data and queries for + tests + +2007-08-01 20:48 hobu + + * INSTALL, Makefile.in, README, aclocal.m4, + regressiontest/Makefile.in, regressiontest/mvrtree/Makefile.in, + regressiontest/rtree/Makefile.in, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeQuery.cc, + regressiontest/tprtree/Makefile.in, src/Makefile.in, + src/mvrtree/Makefile.in, src/rtree/Makefile.in, + src/spatialindex/Makefile.in, src/storagemanager/Makefile.in, + src/tprtree/Makefile.in: add Marios' latest updates + +2007-08-01 20:40 hobu + + * spatialindex.111.zip: oops, don't include zip files + +2007-08-01 20:37 hobu + + * AUTHORS, COPYING, ChangeLog, INSTALL, Makefile.am, Makefile.in, + NEWS, README, aclocal.m4, config.guess, config.sub, configure, + configure.ac, depcomp, include, include/MVRTree.h, + include/MovingPoint.h, include/MovingRegion.h, include/RTree.h, + include/SpatialIndex.h, include/TPRTree.h, include/TimePoint.h, + include/TimeRegion.h, install-sh, ltmain.sh, missing, + mkinstalldirs, regressiontest, regressiontest/Makefile.am, + regressiontest/Makefile.in, regressiontest/mvrtree, + regressiontest/mvrtree/Exhaustive.cc, + regressiontest/mvrtree/Generator.cc, + regressiontest/mvrtree/MVRTreeLoad.cc, + regressiontest/mvrtree/MVRTreeQuery.cc, + regressiontest/mvrtree/Makefile.am, + regressiontest/mvrtree/Makefile.in, regressiontest/mvrtree/test1, + regressiontest/mvrtree/test1/run, regressiontest/mvrtree/test2, + regressiontest/mvrtree/test2/run, regressiontest/rtree, + regressiontest/rtree/Exhaustive.cc, + regressiontest/rtree/Generator.cc, + regressiontest/rtree/Makefile.am, + regressiontest/rtree/Makefile.in, + regressiontest/rtree/RTreeBulkLoad.cc, + regressiontest/rtree/RTreeLoad.cc, + regressiontest/rtree/RTreeQuery.cc, regressiontest/rtree/test1, + regressiontest/rtree/test1/run, regressiontest/rtree/test2, + regressiontest/rtree/test2/run, regressiontest/rtree/test3, + regressiontest/rtree/test3/run, regressiontest/rtree/test4, + regressiontest/rtree/test4/run, regressiontest/tprtree, + regressiontest/tprtree/Exhaustive.cc, + regressiontest/tprtree/Generator.cc, + regressiontest/tprtree/Makefile.am, + regressiontest/tprtree/Makefile.in, + regressiontest/tprtree/RandomGenerator.cc, + regressiontest/tprtree/RandomGenerator.h, + regressiontest/tprtree/TPRTreeLoad.cc, + regressiontest/tprtree/TPRTreeQuery.cc, + regressiontest/tprtree/test1, regressiontest/tprtree/test1/run, + regressiontest/tprtree/test2, regressiontest/tprtree/test2/run, + spatialindex.111.zip, src, src/Makefile.am, src/Makefile.in, + src/mvrtree, src/mvrtree/Index.cc, src/mvrtree/Index.h, + src/mvrtree/Leaf.cc, src/mvrtree/Leaf.h, src/mvrtree/MVRTree.cc, + src/mvrtree/MVRTree.h, src/mvrtree/Makefile.am, + src/mvrtree/Makefile.in, src/mvrtree/Node.cc, src/mvrtree/Node.h, + src/mvrtree/PointerPoolNode.h, src/mvrtree/Statistics.cc, + src/mvrtree/Statistics.h, src/rtree, src/rtree/BulkLoader.cc, + src/rtree/BulkLoader.h, src/rtree/Index.cc, src/rtree/Index.h, + src/rtree/Leaf.cc, src/rtree/Leaf.h, src/rtree/Makefile.am, + src/rtree/Makefile.in, src/rtree/Node.cc, src/rtree/Node.h, + src/rtree/PointerPoolNode.h, src/rtree/RTree.cc, + src/rtree/RTree.h, src/rtree/Statistics.cc, + src/rtree/Statistics.h, src/spatialindex, + src/spatialindex/Makefile.am, src/spatialindex/Makefile.in, + src/spatialindex/MovingPoint.cc, + src/spatialindex/MovingRegion.cc, + src/spatialindex/SpatialIndexImpl.cc, + src/spatialindex/SpatialIndexImpl.h, + src/spatialindex/TimePoint.cc, src/spatialindex/TimeRegion.cc, + src/storagemanager, src/storagemanager/Buffer.cc, + src/storagemanager/Buffer.h, + src/storagemanager/DiskStorageManager.cc, + src/storagemanager/DiskStorageManager.h, + src/storagemanager/Makefile.am, src/storagemanager/Makefile.in, + src/storagemanager/MemoryStorageManager.cc, + src/storagemanager/MemoryStorageManager.h, + src/storagemanager/RandomEvictionsBuffer.cc, + src/storagemanager/RandomEvictionsBuffer.h, src/tprtree, + src/tprtree/Index.cc, src/tprtree/Index.h, src/tprtree/Leaf.cc, + src/tprtree/Leaf.h, src/tprtree/Makefile.am, + src/tprtree/Makefile.in, src/tprtree/Node.cc, src/tprtree/Node.h, + src/tprtree/PointerPoolNode.h, src/tprtree/Statistics.cc, + src/tprtree/Statistics.h, src/tprtree/TPRTree.cc, + src/tprtree/TPRTree.h: add 1.1.1 version of library + +2007-08-01 20:32 hobu + + * .: basic layout + diff --git a/sci-libs/libspatialindex/svn/trunk/HOWTORELEASE.txt b/sci-libs/libspatialindex/svn/trunk/HOWTORELEASE.txt new file mode 100644 index 000000000..10bbac934 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/HOWTORELEASE.txt @@ -0,0 +1,82 @@ + +Steps for Making a libLAS Release +============================================================================== + +:Author: Howard Butler +:Contact: hobu.inc@gmail.com +:Revision: $Revision: 178 $ +:Date: $Date: 2010-03-05 09:19:51 -0500 (Fri, 05 Mar 2010) $ + +This document describes the process for releasing a new version of libspatialindex. + +General Notes +------------------------------------------------------------------------------ + +Release Process + +1) Increment Version Numbers + + - configure.ac + * sidx_version_major + * sidx_version_minor + * sidx_version_micro + - include/Version.h + * SIDX_VERSION_MAJOR + * SIDX_VERSION_MINOR + * SIDX_VERSION_REV + * SIDX_RELEASE_NAME + - makefile.vc's + *PACKAGE_VERSION + +2) Update README to include any relevant info about the release that + might have changed. + +3) Update ChangeLog with svn2cl + +4) Run the regression tests. Really. + +5) Build Windows version + + - Issue nmake and nmake install commands + + :: + + nmake /f makefile.vc clean + nmake /f makefile.vc + nmake /f makefile.vc install + nmake /f makefile.vc package + + +6) Make the source distribution + + :: + + make dist + + +7) Generate MD5 sums + + :: + + md5 spatialindex-src-1.5.0.tar.bz2 > spatialindex-src-1.5.0.tar.bz2.md5 + md5 spatialindex-src-1.5.0.tar.gz > spatialindex-src-1.5.0.tar.gz.md5 + md5 liblas-1.3.1-win32.zip > liblas-1.3.1-win32.zip.md5 + +8) Update http://trac.gispython.org/spatialindex/wiki/Releases + +9) Upload windows and source package as attachments to the new release page. + +10) Tag the release. Use the ``-f`` switch if you are retagging because you + missed something. + + :: + + svn cp http://svn.gispython.org/svn/spatialindex/spatialindex/trunk http://svn.gispython.org/svn/spatialindex/spatialindex/tags/1.5.0 + +11) Write the release notes. Place a copy of the release notes on the release + page you created as well as send an email to spatalindex list announcing the + new release. + + + +$Id: HOWTORELEASE.txt 178 2010-03-05 14:19:51Z hobu $ diff --git a/sci-libs/libspatialindex/svn/trunk/INSTALL b/sci-libs/libspatialindex/svn/trunk/INSTALL new file mode 100644 index 000000000..095b1eb40 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/INSTALL @@ -0,0 +1,231 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PREFIX', the package will +use PREFIX as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/sci-libs/libspatialindex/svn/trunk/INSTALL.WIN b/sci-libs/libspatialindex/svn/trunk/INSTALL.WIN new file mode 100644 index 000000000..52649de1a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/INSTALL.WIN @@ -0,0 +1,28 @@ +Visual Studio 2005: +You have to open the spatialindex.sln solution from the IDE and build. +Unfortunatelly, vcbuild.exe does not work as expected, hence you cannot +build the DLL from the command line. + +Visutal Studio 2008: +Either use the IDE or use vcbuild to compile from the command line: + +To create 32bit DLL: +1. Open a Visual Studio command prompt (or open any shell + and run vcvars32.bat). + +2a. Release build: + Run vcbuild.exe /useenv spatialindex.sln "Release|Win32" +2b. Debug build: + Run vcbuild.exe /useenv spatialindex.sln "Debug|Win32" + +To create 64bit DLL: +1. Open a Visual Studio x64 command prompt (or open any shell + and run vcvarsall.bat x64). + +2a. Release build: + Run vcbuild.exe /useenv spatialindex.sln "Release|x64" +2b. Debug build: + Run vcbuild.exe /useenv spatialindex.sln "Debug|x64" + +Enjoy! + diff --git a/sci-libs/libspatialindex/svn/trunk/Makefile.am b/sci-libs/libspatialindex/svn/trunk/Makefile.am new file mode 100644 index 000000000..9b4c2eced --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/Makefile.am @@ -0,0 +1,23 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +SUBDIRS = src . regressiontest include + +lib_LTLIBRARIES = libspatialindex.la libspatialindex_c.la + +libspatialindex_la_SOURCES = +libspatialindex_la_LIBADD = \ + src/spatialindex/liblibrary.la \ + src/storagemanager/libstoragemanager.la \ + src/rtree/librtree.la \ + src/mvrtree/libmvrtree.la \ + src/tprtree/libtprtree.la \ + src/tools/libtools.la + +libspatialindex_c_la_SOURCES = +libspatialindex_c_la_LIBADD = \ + libspatialindex.la \ + src/capi/libsidxc.la + +libspatialindex_la_LDFLAGS = -version-info 1:0:0 +libspatialindex_c_la_LDFLAGS = -version-info 1:0:0 -lstdc++ + +EXTRA_DIST = makefile.vc INSTALL.WIN spatialindex.sln spatialindex-vc/spatialindex.vcproj diff --git a/sci-libs/libspatialindex/svn/trunk/NEWS b/sci-libs/libspatialindex/svn/trunk/NEWS new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/NEWS diff --git a/sci-libs/libspatialindex/svn/trunk/README b/sci-libs/libspatialindex/svn/trunk/README new file mode 100644 index 000000000..a5f50a4e0 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/README @@ -0,0 +1,423 @@ +***************************************************************************** + SpatialIndex Reference +***************************************************************************** + +:Author: Marios Hadjieleftheriou +:Contact: mhadji@gmail.com +:Revision: $Revision: 203 $ +:Date: $Date: 2011-05-18 11:20:08 -0400 (Wed, 18 May 2011) $ + +.. The next heading encountered becomes our H2 +.. + +.. sectnum:: + +.. contents:: + :depth: 2 + :backlinks: top + +------------------------------------------------------------------------------ +Introduction +------------------------------------------------------------------------------ + +You have downloaded the SpatialIndex Library. This is free software under LGPL. +The library is in beta testing stage. Use at your own risk. + +The purpose of this library is to provide: + 1. An extensible framework that will support robust spatial indexing + methods. + 2. Support for sophisticated spatial queries. Range, point location, + nearest neighbor and k-nearest neighbor as well as parametric + queries (defined by spatial constraints) should be easy to deploy and run. + 3. Easy to use interfaces for inserting, deleting and updating information. + 4. Wide variety of customization capabilities. Basic index and storage + characteristics like the page size, node capacity, minimum fan-out, + splitting algorithm, etc. should be easy to customize. + 5. Index persistence. Internal memory and external memory structures + should be supported. Clustered and non-clustered indices should + be easy to be persisted. + +------------------------------------------------------------------------------ +Installation +------------------------------------------------------------------------------ + +First run autogen.sh to generate the configure scripts. +By default include files and library files will be installed in /usr/local. If +you would like to use a different installation directory (e.g., in case +that you do not have root access) run the configure script with +the --prefix option: + +:: + + ./configure --prefix=/home/marioh/usr + +Make the library:: + + make + +Install the library:: + + make install + +------------------------------------------------------------------------------ +Using the Library +------------------------------------------------------------------------------ + +You are ready to use the library. All you have to +do is to include the file SpatialIndex.h in your source +files and then compile with the following options: + +:: + + g++ MyFile.cc -o MyFile -L/home/marioh/usr/lib -I/home/marioh/usr/include -lpthread -lspatialindex + +If the library is installed in the default /usr/local path, then the +-I and -L options are not necessary. + +If you are compiling on Mac OS X you will need to add the -bind_at_load +option when linking against the dynamic link libraries. OS X Tiger should +work out of the box, however, with XCode 3.0. + +------------------------------------------------------------------------------ +Library Overview +------------------------------------------------------------------------------ + +The library currently consists of six packages: + 1. The core spatialindex utilities. + 2. The storagemanager files. + 3. The spatialindex interfaces. + 4. The rtree index. + 5. The mvrtree index. + 6. The tprtree index. + +I will briefly present the basic features supported by each package. +For more details you will have to refer to the code, for now. + +Spatial Index Utilities +------------------------------------------------------------------------------ + +To provide common constructors and uniform initialization for all objects +provided by the library a PropertySet class is provided. A PropertySet +associates strings with Variants. Each property corresponds to one string. + +A basic implementation of a Variant is also provided that supports a +number of data types. The supported data types can be found in SpatialIndex.h + +PropertySet supports three functions: + + 1. getProperty returns the Variant associated with the given string. + 2. setProperty associates the given Variant with the given string. + 3. removeProperty removes the specified property from the PropertySet. + +A number of exceptions are also defined here. All exceptions extend +Exception and thus provide the what() method that returns a string +representation of the exception with useful comments. It is advisable to +use enclosing try/catch blocks when using any library objects. Many +constructors throw exceptions when invalid initialization properties are specified. + +A general IShape interface is defined. All shape classes should extend +IShape. Basic Region and Point classes are already provided. Please +check Region.h and Point.h for further details. + +Storage Manager +------------------------------------------------------------------------------ + +The library provides a common interface for storage management of all +indices. It consists of the IStorageManager interface, which provides functions +for storing and retrieving entities. An entity is viewed as a simple byte +array; hence it can be an index entry, a data entry or anything else that the +user wants to store. The storage manager interface is generic and does not apply +only to spatial indices. + +Classes that implement the IStorageManager interface decide on how to +store entities. simple main memory implementation is provided, for example, +that stores the entities using a vector, associating every entity with a +unique ID (the entry's index in the vector). A disk based storage manager +could choose to store the entities in a simple random access file, or a +database storage manager could store them in a relational table, etc. as long +as unique IDs are associated with every entity. Also, storage managers should +implement their own paging, compaction and deletion policies transparently +from the callers (be it an index or a user). + +The storeByteArray method gets a byte array and its length and an entity ID. +If the caller specifies NewPage as the input ID, the storage manager allocates +a new ID, stores the entity and returns the ID associated with the entity. +If, instead, the user specifies an already existing ID the storage manager +overwrites the old data. An exception is thrown if the caller requests +an invalid ID to be overwritten. + +The loadByteArray method gets an entity ID and returns the associated byte +array along with its length. If an invalid ID is requested, an exception is thrown. + +The deleteByteArray method removes the requested entity from storage. + +The storage managers should have no information about the types of entities +that are stored. There are three main reasons for this decision: + + 1. Any number of spatial indices can be stored in a single storage manager + (i.e. the same relational table, or binary file, or hash table, etc., can + be used to store many indices) using an arbitrary number of pages and + a unique index ID per index (this will be discussed shortly). + 2. Both clustered and non-clustered indices can be supported. A clustered + index stores the data associated with the entries that it contains along + with the spatial information that it indexes. A non-clustered index stores + only the spatial information of its entries. Any associated data are + stored separately and are associated with the index entries by a unique ID. + To support both types of indices, the storage manager interface should be + quite generic, allowing the index to decide how to store its data. + Otherwise clustered and non-clustered indices would have to be + implemented separately. + 3. Decision flexibility. For example, the users can choose a clustered index + that will take care of storing everything. They can choose a main memory + non-clustered index and store the actual data in MySQL. They can choose + a disk based non-clustered index and store the data manually in a + separate binary file or even in the same storage manager but doing a low + level customized data processing. + +Two storage managers are provided in the current implementation: + + 1) MemoryStorageManager + 2) DiskStorageManager + +MemoryStorageManager +~~~~~~~~~~~~~~~~~~~~~~~ + +As it is implied be the name, this is a main memory implementation. Everything +is stored in main memory using a simple vector. No properties are needed to +initialize a MemoryStorageManager object. When a MemoryStorageManager instance +goes out of scope, all data that it contains are lost. + +DiskStorageManager +~~~~~~~~~~~~~~~~~~~~~~~ + +The disk storage manager uses two random access files for storing information. +One with extension .idx and the other with extension .dat. + +A list of all the supported properties that can be provided during +initialization, follows: + +========= ======== =========================================================== +Property Type Description +========= ======== =========================================================== +FileName VT_PCHAR The base name of the file to open (no extension) +Overwrite VT_BOOL If Overwrite is true and a storage manager with the + specified filename already exists, it will be + truncated and overwritten. All data will be lost. +PageSize VT_ULONG The page size to use. If the specified filename + already exists and Overwrite is false, PageSize is ignored. +========= ======== =========================================================== + +For entities that are larger than the page size, multiple pages are used. +Although, the empty space on the last page is lost. Also, there is no effort +whatsoever to use as many sequential pages as possible. A future version +might support sequential I/O. Thus, real clustered indices cannot be supported yet. + +The purpose of the .idx file is to store vital information like the page size, +the next available page, a list of empty pages and the sequence of pages +associated with every entity ID. + +This class also provides a flush method that practically overwrites the +.idx file and syncs both file pointers. + +The .idx file is loaded into main memory during initialization and is +written to disk only after flushing the storage manager or during object +destruction. In case of an unexpected failure changes to the storage manager +will be lost due to a stale .idx file. Avoiding such disasters is future work. + +SpatialIndex Interfaces +------------------------------------------------------------------------------ + +A spatial index is any index structure that accesses spatial information +efficiently. It could range from a simple grid file to a complicated tree +structure. A spatial index indexes entries of type IEntry, which can be index +nodes, leaf nodes, data etc. depending on the structure characteristics. +The appropriate interfaces with useful accessor methods should be provided +for all types of entries. + +A spatial index should implement the ISpatialIndex interface. + +The containmentQuery method requires a query shape and a reference to a +valid IVisitor instance (described shortly). The intersectionQuery method +is the same. Both accept an IShape as the query. If the query shape is a simple +Region, than a classic range query is performed. The user though has the +ability to create her own shapes, thus defining her own intersection and +containment methods making possible to run any kind of range query without +having to modify the index. An example of a trapezoidal query is given in the +regressiontest directory. Have in mind that it is the users responsibility +to implement the correct intersection and containment methods between their +shape and the type of shapes that are stored by the specific index that they +are planning to use. For example, if an rtree index will be used, a trapezoid +should define intersection and containment between itself and Regions, since +all rtree nodes are of type Region. Hence, the user should have some knowledge +about the index internal representation, to run more sophisticated queries. + +A point location query is performed using the pointLocationQuery method. It +takes the query point and a visitor as arguments. + +Nearest neighbor queries can be performed with the nearestNeighborQuery method. +Its first argument is the number k of nearest neighbors requested. This +method also requires the query shape and a visitor object. The default +implementation uses the getMinimumDistance function of IShape for calculating +the distance of the query from the rectangular node and data entries stored +in the tree. A more sophisticated distance measure can be used by implementing +the INearestNeighborComparator interface and passing it as the last argument +of nearestNeighborQuery. For example, a comparator is necessary when the query +needs to be checked against the actual data stored in the tree, instead of +the rectangular data entry approximations stored in the leaves. + +For customizing queries the IVisitor interface (based on the Visitor +pattern [gamma94]) provides callback functions for visiting index and +leaf nodes, as well as data entries. Node and data information can be obtained +using the INode and IData interfaces (both extend IEntry). Examples of using +this interface include visualizing a query, counting the number of leaf +or index nodes visited for a specific query, throwing alerts when a +specific spatial region is accessed, etc. + +The queryStrategy method provides the ability to design more sophisticated +queries. It uses the IQueryStrategy interface as a callback that is called +continuously until no more entries are requested. It can be used to +implement custom query algorithms (based on the strategy pattern [gamma94]). + +A data entry can be inserted using the insertData method. The insertion +function will convert any shape into an internal representation depending on +the index. Every inserted object should be assigned an ID (called object +identifier) that will allow updating, deleting and reporting the object. +It is the responsibility of the caller to provide the index with IDs +(unique or not). Also, a byte array can be associated with an entry. The +byte arrays are stored along with the spatial information inside the leaf +nodes. Clustered indices can be supported in that way. The byte array can +also by null (in which case the length field should be zero), and no extra +space should be used per node. + +A data entry can be deleted using the deleteData method. The object shape +and ID should be provided. Spatial indices cluster objects according to +spatial characteristics and not IDs. Hence, the shape is essential for +locating and deleting an entry. + +Useful statistics are provided through the IStatistics interface and +the getStatistics method. + +Method getIndexProperties returns a PropertySet with all useful index +properties like dimensionality etc. + +A NodeCommand interface is provided for customizing Node operations. Using +the addWriteNodeCommand, addReadNodeCommand and addDeleteNodeCommand methods, +custom command objects are added in listener lists and get executed after +the corresponding operations. + +The isIndexValid method performs internal checks for testing the +integrity of a structure. It is used for debugging purposes. + +When a new index is created a unique index ID should be assigned to it, that +will be used when reloading the index from persistent storage. This index ID +should be returned as an IndexIdentifier property in the instance of the +PropsertySet that was used for constructing the index instance. Using +index IDs, multiple indices can be stored in the same storage manager. +It is the users responsibility to manager the index IDs. Associating the +wrong index ID with the wrong storage manager or index type has undefined +results. + +The RTree Package +------------------------------------------------------------------------------ + +The RTree index [guttman84] is a balanced tree structure that consists of +index nodes, leaf nodes and data. Every node (leaf and index) has a fixed +capacity of entries, (the node capacity) chosen at index creation An RTree +abstracts the data with their Minimum Bounding Region (MBR) and clusters +these MBRs according to various heuristics in the leaf nodes. Queries are +evaluated from the root of the tree down the leaves. Since the index is +balanced nodes can be under full. They cannot be empty though. A fill +factor specifies the minimum number of entries allowed in any node. The +fill factor is usually close to 70%. + +RTree creation involves: + + 1. Deciding if the index will be internal or external memory and selecting + the appropriate storage manager. + 2. Choosing the index and leaf capacity (also known as fan-out). + 3. Choosing the fill factor (from 1% to 99% of the node capacity). + 4. Choosing the dimensionality of the data. + 5. Choosing the insert/update policy (the RTree variant). + +If an already stored RTree is being reloaded for reuse, only the index ID +needs to be supplied during construction. In that case, some options cannot +be modified. These include: the index and leaf capacity, the fill factor and +the dimensionality. Note here, that the RTree variant can actually be +modified. The variant affects only when and how splitting occurs, and +thus can be changed at any time. + +An initialization PropertySet is used for setting the above options, +complying with the following property strings: + +========================== =========== ============================================================ +Property Type Description +========================== =========== ============================================================ +IndexIndentifier VT_LONG If specified an existing index will be + opened from the supplied storage manager with + the given index id. Behavior is unspecified + if the index id or the storage manager are incorrect. +Dimension VT_ULONG Dimensionality of the data that will be inserted. +IndexCapacity VT_ULONG The index node capacity. Default is 100. +LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. +FillFactor VT_DOUBLE The fill factor. Default is 70% +TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar +NearMinimumOverlapFactor VT_ULONG Default is 32. +SplitDistributionFactor VT_DOUBLE Default is 0.4 +ReinsertFactor VT_DOUBLE Default is 0.3 +EnsureTightMBRs VT_BOOL Default is true +IndexPoolCapacity VT_LONG Default is 100 +LeafPoolCapacity VT_LONG Default is 100 +RegionPoolCapacity VT_LONG Default is 1000 +PointPoolCapacity VT_LONG Default is 500 +========================== =========== ============================================================ + +Performance +------------------------------------------------------------------------------ + +Dataset size, data density, etc. have nothing to do with capacity and page +size. What you are trying to achieve is fast reads from the disk and take +advantage of disk buffering and prefetching. + +Normally, you select the page size to be equal to the disk page size (depends +on how you format the drive). Then you choose the node capacity to be enough +to fill the whole page (including data entries if you have any). + +There is a tradeoff though in making node capacity too large. The larger the +capacity, the longer the "for loops" for inserting, deleting, locating node +entries take (CPU time). On the other hand, the larger the capacity the +shorter the tree becomes, reducing the number of random IOs to reach the +leaves. Hence, you might want to fit multiple nodes (of smaller capacity) +inside a single page to balance I/O and CPU cost, in case your disk page size +is too large. + +Finally, if you have enough buffer space to fit most of the index nodes in +main memory, then large capacities do not make too much sense, because the +height of the tree does not matter any more. Of course, the smaller the +capacity, the larger the number of leaf nodes you will have to retrieve from +disk for range queries (point queries and nearest neighbor queries will not +suffer that much). So very small capacities hurt as well. + +There is another issue when trying to fit multiple nodes per page: Leftover +space. You might have leftover space due to data entries that do not have a +fixed size. Unfortunately, in that case, leftover space per page is lost, +negatively impacting space usage. + +Selecting the right page size is easy; make it equal to the disk page size. +Selecting the right node capacity is an art... + +------------------------------------------------------------------------------ +Contact Information +------------------------------------------------------------------------------ + +You can contact me at mhadji@gmail.com for further assistance. Please read the +above information carefully and also do not be afraid to browse through the +code and especially the test files inside regressiontest directory. + +------------------------------------------------------------------------------ +References +------------------------------------------------------------------------------ +[guttman84] "R-Trees: A Dynamic Index Structure for Spatial Searching" + Antonin Guttman, Proc. 1984 ACM-SIGMOD Conference on Management of Data (1985), 47-57. +[gamma94] "Design Patterns: Elements of Reusable Object-Oriented Software" + Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison Wesley. October 1994. + diff --git a/sci-libs/libspatialindex/svn/trunk/autogen.sh b/sci-libs/libspatialindex/svn/trunk/autogen.sh new file mode 100755 index 000000000..0c5823b7f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/autogen.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# $Id: autogen.sh 61 2007-12-11 20:13:48Z hobu $ +# +# Autotools boostrapping script +# +giveup() +{ + echo + echo " Something went wrong, giving up!" + echo + exit 1 +} + +OSTYPE=`uname -s` + +for libtoolize in glibtoolize libtoolize; do + LIBTOOLIZE=`which $libtoolize 2>/dev/null` + if test "$LIBTOOLIZE"; then + break; + fi +done + +#AMFLAGS="--add-missing --copy --force-missing" +AMFLAGS="--add-missing --copy" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal || giveup +#echo "Running autoheader" +#autoheader || giveup +echo "Running libtoolize" +$LIBTOOLIZE --force --copy || giveup +echo "Running automake" +automake $AMFLAGS # || giveup +echo "Running autoconf" +autoconf || giveup + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/sci-libs/libspatialindex/svn/trunk/configure.ac b/sci-libs/libspatialindex/svn/trunk/configure.ac new file mode 100644 index 000000000..dcf4e1cd1 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/configure.ac @@ -0,0 +1,71 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) + +m4_define([sidx_version_major], [1]) +m4_define([sidx_version_minor], [6]) +m4_define([sidx_version_micro], [1]) +m4_define([sidx_version], + [sidx_version_major.sidx_version_minor.sidx_version_micro]) + +AC_INIT([spatialindex], [sidx_version], [mhadji@gmail.com], [spatialindex-src]) +AC_CANONICAL_BUILD + +debug_default="no" +CXXFLAGS="$CXXFLAGS" + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_LIBTOOL +AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects]) + +# Checks for header files. +AC_CHECK_HEADERS(fcntl.h,, [AC_MSG_ERROR([cannot find fcntl.h, bailing out])]) +AC_CHECK_HEADERS(unistd.h,, [AC_MSG_ERROR([cannot find unistd.h, bailing out])]) +AC_CHECK_HEADERS(sys/types.h,, [AC_MSG_ERROR([cannot find sys/types.h, bailing out])]) +AC_CHECK_HEADERS(sys/stat.h,, [AC_MSG_ERROR([cannot find sys/stat.h, bailing out])]) +AC_CHECK_HEADERS(pthread.h, [LIBS="$LIBS -lpthread"]) +AC_CHECK_HEADERS(sys/resource.h,, [AC_MSG_ERROR([cannot find sys/resource.h, bailing out])]) +AC_CHECK_HEADERS(sys/time.h,, [AC_MSG_ERROR([cannot find sys/time.h, bailing out])]) +AC_CHECK_HEADERS(stdint.h,, [AC_MSG_ERROR([cannot find stdint.h, bailing out])]) +#MH_CXX_HEADER_TOOLS + +LIBS="$LIBS" + +AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging [default=$debug_default]],, enable_debug=$debug_default) + +if test "x$enable_debug" = "xyes"; then + CXXFLAGS="$CXXFLAGS -g -DDEBUG" + AC_MSG_RESULT(checking wether debug information is enabled... yes) +else + CXXFLAGS="$CXXFLAGS -O2 -DNDEBUG" + AC_MSG_RESULT(checking wether debug information is enabled... no) +fi + +# Checks for library functions. +AC_CHECK_FUNCS([gettimeofday bzero memset memcpy bcopy]) + +AC_CONFIG_FILES([ Makefile + include/Makefile + include/capi/Makefile + include/tools/Makefile + src/Makefile + src/capi/Makefile + src/spatialindex/Makefile + src/storagemanager/Makefile + src/rtree/Makefile + src/mvrtree/Makefile + src/tprtree/Makefile + src/tools/Makefile + regressiontest/Makefile + regressiontest/rtree/Makefile + regressiontest/mvrtree/Makefile + regressiontest/tprtree/Makefile]) + +AC_OUTPUT + diff --git a/sci-libs/libspatialindex/svn/trunk/depcomp b/sci-libs/libspatialindex/svn/trunk/depcomp new file mode 100644 index 000000000..11e2d3bfe --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/depcomp @@ -0,0 +1,522 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to <bug-automake@gnu.org>. +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + elif test -f "$tmpdepfile2"; then + tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/include/.svn/all-wcprops new file mode 100644 index 000000000..f3def12ad --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/all-wcprops @@ -0,0 +1,83 @@ +K 25 +svn:wc:ra_dav:version-url +V 53 +/spatialindex/!svn/ver/199/spatialindex/trunk/include +END +MovingPoint.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/MovingPoint.h +END +Point.h +K 25 +svn:wc:ra_dav:version-url +V 61 +/spatialindex/!svn/ver/154/spatialindex/trunk/include/Point.h +END +LineSegment.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/154/spatialindex/trunk/include/LineSegment.h +END +RTree.h +K 25 +svn:wc:ra_dav:version-url +V 61 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/RTree.h +END +TimeRegion.h +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/TimeRegion.h +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/138/spatialindex/trunk/include/Makefile.am +END +MovingRegion.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/MovingRegion.h +END +Region.h +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/154/spatialindex/trunk/include/Region.h +END +MVRTree.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/MVRTree.h +END +SpatialIndex.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/154/spatialindex/trunk/include/SpatialIndex.h +END +TPRTree.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/TPRTree.h +END +Version.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/199/spatialindex/trunk/include/Version.h +END +TimePoint.h +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/TimePoint.h +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/dir-prop-base new file mode 100644 index 000000000..a57f5442b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 21 +Makefile +Makefile.in + +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/entries b/sci-libs/libspatialindex/svn/trunk/include/.svn/entries new file mode 100644 index 000000000..aeddcb130 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/entries @@ -0,0 +1,476 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/include +http://svn.gispython.org/spatialindex + + + +2010-12-04T21:22:32.514652Z +199 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Point.h +file + + + + +2011-08-01T00:42:34.325197Z +1ed931b7af77efe583a8337fa71fcf6d +2009-10-21T17:35:24.248978Z +154 +hobu + + + + + + + + + + + + + + + + + + + + + +2294 + +TimeRegion.h +file + + + + +2011-08-01T00:42:34.325197Z +555523ea6f23f79e31f683e7f65b308a +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +4037 + +MovingRegion.h +file + + + + +2011-08-01T00:42:34.329111Z +00337cf9f8e1f3b6faee2fbfb434176e +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +5995 + +TimePoint.h +file + + + + +2011-08-01T00:42:34.329111Z +740894d437638cb0b385159a3d0f270a +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +3299 + +MovingPoint.h +file + + + + +2011-08-01T00:42:34.325197Z +f547925166984beeec6b0ad48ad1d6ff +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2610 + +LineSegment.h +file + + + + +2011-08-01T00:42:34.325197Z +ccf565aff106626f0cb6361e6221d02d +2009-10-21T17:35:24.248978Z +154 +hobu + + + + + + + + + + + + + + + + + + + + + +2695 + +tools +dir + +RTree.h +file + + + + +2011-08-01T00:42:34.325197Z +0028957bca65f395aaee0ccfa3ff4d4a +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2669 + +Region.h +file + + + + +2011-08-01T00:42:34.329111Z +7a5710c13bc43656d443e9af1881bfc5 +2009-10-21T17:35:24.248978Z +154 +hobu + + + + + + + + + + + + + + + + + + + + + +3156 + +Makefile.am +file + + + + +2011-08-01T00:42:34.325197Z +118d4947ba41634c80fdcebe9227658b +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +341 + +MVRTree.h +file + + + + +2011-08-01T00:42:34.329111Z +5e61009edcb9b663ab57d80d5e86cbd0 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2191 + +Version.h +file + + + + +2011-08-01T00:42:34.329111Z +545d424eb2913568593a3760f1c6daa9 +2010-12-04T21:22:32.514652Z +199 +hobu + + + + + + + + + + + + + + + + + + + + + +1311 + +TPRTree.h +file + + + + +2011-08-01T00:42:34.329111Z +56a57e2e61cf2a644972d4a6ebd697ae +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2170 + +SpatialIndex.h +file + + + + +2011-08-01T00:42:34.329111Z +6b31cbdc93b1939610009bd5e6643e1c +2009-10-21T17:35:24.248978Z +154 +hobu + + + + + + + + + + + + + + + + + + + + + +7886 + +capi +dir + diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/LineSegment.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/LineSegment.h.svn-base new file mode 100644 index 000000000..ab09e5291 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/LineSegment.h.svn-base @@ -0,0 +1,83 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL LineSegment : public Tools::IObject, public virtual IShape + { + public: + LineSegment(); + LineSegment(const double* startPoint, const double* endPoint, uint32_t dimension); + LineSegment(const Point& startPoint, const Point& endPoint); + LineSegment(const LineSegment& l); + virtual ~LineSegment(); + + virtual LineSegment& operator=(const LineSegment& p); + virtual bool operator==(const LineSegment& p) const; + + // + // IObject interface + // + virtual LineSegment* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& length); + + // + // IShape interface + // + virtual bool intersectsShape(const IShape& in) const; + virtual bool containsShape(const IShape& in) const; + virtual bool touchesShape(const IShape& in) const; + virtual void getCenter(Point& out) const; + virtual uint32_t getDimension() const; + virtual void getMBR(Region& out) const; + virtual double getArea() const; + virtual double getMinimumDistance(const IShape& in) const; + + virtual double getMinimumDistance(const Point& p) const; + //virtual double getMinimumDistance(const Region& r) const; + virtual double getRelativeMinimumDistance(const Point& p) const; + virtual double getRelativeMaximumDistance(const Region& r) const; + virtual double getAngleOfPerpendicularRay(); + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + uint32_t m_dimension; + double* m_pStartPoint; + double* m_pEndPoint; + + friend class Region; + friend class Point; + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const LineSegment& pt); + }; // Point + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const LineSegment& pt); +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MVRTree.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MVRTree.h.svn-base new file mode 100644 index 000000000..aa1aeaab5 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MVRTree.h.svn-base @@ -0,0 +1,83 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + SIDX_DLL enum MVRTreeVariant + { + RV_LINEAR = 0x0, + RV_QUADRATIC, + RV_RSTAR + }; + + SIDX_DLL enum PersistenObjectIdentifier + { + PersistentIndex = 0x1, + PersistentLeaf = 0x2 + }; + + SIDX_DLL enum RangeQueryType + { + ContainmentQuery = 0x1, + IntersectionQuery = 0x2 + }; + + class SIDX_DLL Data : public IData, public Tools::ISerializable + { + public: + Data(uint32_t len, byte* pData, TimeRegion& r, id_type id); + virtual ~Data(); + + virtual Data* clone(); + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + virtual void getData(uint32_t& len, byte** data) const; + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + id_type m_id; + TimeRegion m_region; + byte* m_pData; + uint32_t m_dataLength; + }; // Data + + SIDX_DLL ISpatialIndex* returnMVRTree(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL ISpatialIndex* createNewMVRTree( + IStorageManager& in, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + MVRTreeVariant rv, + id_type& out_indexIdentifier + ); + SIDX_DLL ISpatialIndex* loadMVRTree( + IStorageManager& in, + id_type indexIdentifier + ); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..e061275ce --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,16 @@ +SUBDIRS = tools capi + +spatialindexdir = $(includedir)/spatialindex + +spatialindex_HEADERS = SpatialIndex.h \ + RTree.h \ + MVRTree.h \ + TPRTree.h \ + Point.h \ + Region.h \ + LineSegment.h \ + TimePoint.h \ + TimeRegion.h \ + MovingPoint.h \ + MovingRegion.h \ + Version.h
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MovingPoint.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MovingPoint.h.svn-base new file mode 100644 index 000000000..bca600a5b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MovingPoint.h.svn-base @@ -0,0 +1,79 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL MovingPoint : public TimePoint, public IEvolvingShape + { + public: + MovingPoint(); + MovingPoint(const double* pCoords, const double* pVCoords, const Tools::IInterval& ti, uint32_t dimension); + MovingPoint(const double* pCoords, const double* pVCoords, double tStart, double tEnd, uint32_t dimension); + MovingPoint(const Point& p, const Point& vp, const Tools::IInterval& ti); + MovingPoint(const Point& p, const Point& vp, double tStart, double tEnd); + MovingPoint(const MovingPoint& p); + virtual ~MovingPoint(); + + virtual MovingPoint& operator=(const MovingPoint& p); + virtual bool operator==(const MovingPoint& p) const; + + virtual double getCoord(uint32_t index, double t) const; + virtual double getProjectedCoord(uint32_t index, double t) const; + virtual double getVCoord(uint32_t index) const; + virtual void getPointAtTime(double t, Point& out) const; + + // + // IObject interface + // + virtual MovingPoint* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // IEvolvingShape interface + // + virtual void getVMBR(Region& out) const; + virtual void getMBRAtTime(double t, Region& out) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + private: + void initialize( + const double* pCoords, const double* pVCoords, + double tStart, double tEnd, uint32_t dimension); + + public: + double* m_pVCoords; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingPoint& pt); + }; // MovingPoint + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingPoint& pt); +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MovingRegion.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MovingRegion.h.svn-base new file mode 100644 index 000000000..d25c50688 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/MovingRegion.h.svn-base @@ -0,0 +1,155 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL MovingRegion : public TimeRegion, public IEvolvingShape + { + public: + MovingRegion(); + MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + const Tools::IInterval& ti, uint32_t dimension); + MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension); + MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + const Tools::IInterval& ti); + MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + double tStart, double tEnd); + MovingRegion(const Region& mbr, const Region& vbr, const Tools::IInterval& ivI); + MovingRegion(const Region& mbr, const Region& vbr, double tStart, double tEnd); + MovingRegion(const MovingPoint& low, const MovingPoint& high); + MovingRegion(const MovingRegion& in); + virtual ~MovingRegion(); + + virtual MovingRegion& operator=(const MovingRegion& r); + virtual bool operator==(const MovingRegion&) const; + + bool isShrinking() const; + + virtual double getLow(uint32_t index, double t) const; + virtual double getHigh(uint32_t index, double t) const; + virtual double getExtrapolatedLow(uint32_t index, double t) const; + virtual double getExtrapolatedHigh(uint32_t index, double t) const; + virtual double getVLow(uint32_t index) const; + virtual double getVHigh(uint32_t index) const; + + virtual bool intersectsRegionInTime(const MovingRegion& r) const; + virtual bool intersectsRegionInTime(const MovingRegion& r, Tools::IInterval& out) const; + virtual bool intersectsRegionInTime(const Tools::IInterval& ivI, const MovingRegion& r, Tools::IInterval& ret) const; + virtual bool containsRegionInTime(const MovingRegion& r) const; + virtual bool containsRegionInTime(const Tools::IInterval& ivI, const MovingRegion& r) const; + virtual bool containsRegionAfterTime(double t, const MovingRegion& r) const; + + virtual double getProjectedSurfaceAreaInTime() const; + virtual double getProjectedSurfaceAreaInTime(const Tools::IInterval& ivI) const; + + virtual double getCenterDistanceInTime(const MovingRegion& r) const; + virtual double getCenterDistanceInTime(const Tools::IInterval& ivI, const MovingRegion& r) const; + + virtual bool intersectsRegionAtTime(double t, const MovingRegion& r) const; + virtual bool containsRegionAtTime(double t, const MovingRegion& r) const; + + virtual bool intersectsPointInTime(const MovingPoint& p) const; + virtual bool intersectsPointInTime(const MovingPoint& p, Tools::IInterval& out) const; + virtual bool intersectsPointInTime(const Tools::IInterval& ivI, const MovingPoint& p, Tools::IInterval& out) const; + virtual bool containsPointInTime(const MovingPoint& p) const; + virtual bool containsPointInTime(const Tools::IInterval& ivI, const MovingPoint& p) const; + + //virtual bool intersectsPointAtTime(double t, const MovingRegion& in) const; + //virtual bool containsPointAtTime(double t, const MovingRegion& in) const; + + virtual void combineRegionInTime(const MovingRegion& r); + virtual void combineRegionAfterTime(double t, const MovingRegion& r); + virtual void getCombinedRegionInTime(MovingRegion& out, const MovingRegion& in) const; + virtual void getCombinedRegionAfterTime(double t, MovingRegion& out, const MovingRegion& in) const; + + virtual double getIntersectingAreaInTime(const MovingRegion& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const MovingRegion& r) const; + + // + // IObject interface + // + virtual MovingRegion* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // IEvolvingShape interface + // + virtual void getVMBR(Region& out) const; + virtual void getMBRAtTime(double t, Region& out) const; + + // + // ITimeShape interface + // + virtual double getAreaInTime() const; + virtual double getAreaInTime(const Tools::IInterval& ivI) const; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + private: + void initialize( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension); + + public: + class CrossPoint + { + public: + double m_t; + uint32_t m_dimension; + uint32_t m_boundary; + const MovingRegion* m_to; + + struct ascending: public std::binary_function<CrossPoint&, CrossPoint&, bool> + { + bool operator()(const CrossPoint& __x, const CrossPoint& __y) const { return __x.m_t > __y.m_t; } + }; + }; // CrossPoint + + public: + double* m_pVLow; + double* m_pVHigh; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingRegion& r); + }; // MovingRegion + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingRegion& r); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Point.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Point.h.svn-base new file mode 100644 index 000000000..51cb4b618 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Point.h.svn-base @@ -0,0 +1,77 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL Point : public Tools::IObject, public virtual IShape + { + public: + Point(); + Point(const double* pCoords, uint32_t dimension); + Point(const Point& p); + virtual ~Point(); + + virtual Point& operator=(const Point& p); + virtual bool operator==(const Point& p) const; + + // + // IObject interface + // + virtual Point* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& length); + + // + // IShape interface + // + virtual bool intersectsShape(const IShape& in) const; + virtual bool containsShape(const IShape& in) const; + virtual bool touchesShape(const IShape& in) const; + virtual void getCenter(Point& out) const; + virtual uint32_t getDimension() const; + virtual void getMBR(Region& out) const; + virtual double getArea() const; + virtual double getMinimumDistance(const IShape& in) const; + + virtual double getMinimumDistance(const Point& p) const; + + virtual double getCoordinate(uint32_t index) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + uint32_t m_dimension; + double* m_pCoords; + + friend class Region; + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const Point& pt); + }; // Point + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const Point& pt); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/RTree.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/RTree.h.svn-base new file mode 100644 index 000000000..4303b9e96 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/RTree.h.svn-base @@ -0,0 +1,102 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + SIDX_DLL enum RTreeVariant + { + RV_LINEAR = 0x0, + RV_QUADRATIC, + RV_RSTAR + }; + + SIDX_DLL enum BulkLoadMethod + { + BLM_STR = 0x0 + }; + + SIDX_DLL enum PersistenObjectIdentifier + { + PersistentIndex = 0x1, + PersistentLeaf = 0x2 + }; + + SIDX_DLL enum RangeQueryType + { + ContainmentQuery = 0x1, + IntersectionQuery = 0x2 + }; + + class SIDX_DLL Data : public IData, public Tools::ISerializable + { + public: + Data(uint32_t len, byte* pData, Region& r, id_type id); + virtual ~Data(); + + virtual Data* clone(); + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + virtual void getData(uint32_t& len, byte** data) const; + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + id_type m_id; + Region m_region; + byte* m_pData; + uint32_t m_dataLength; + }; // Data + + SIDX_DLL ISpatialIndex* returnRTree(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL ISpatialIndex* createNewRTree( + IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + RTreeVariant rv, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + RTreeVariant rv, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + IStorageManager& sm, + Tools::PropertySet& ps, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* loadRTree(IStorageManager& in, id_type indexIdentifier); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Region.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Region.h.svn-base new file mode 100644 index 000000000..feddaee10 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Region.h.svn-base @@ -0,0 +1,97 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL Region : public Tools::IObject, public virtual IShape + { + public: + Region(); + Region(const double* pLow, const double* pHigh, uint32_t dimension); + Region(const Point& low, const Point& high); + Region(const Region& in); + virtual ~Region(); + + virtual Region& operator=(const Region& r); + virtual bool operator==(const Region&) const; + + // + // IObject interface + // + virtual Region* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& length); + + // + // IShape interface + // + virtual bool intersectsShape(const IShape& in) const; + virtual bool containsShape(const IShape& in) const; + virtual bool touchesShape(const IShape& in) const; + virtual void getCenter(Point& out) const; + virtual uint32_t getDimension() const; + virtual void getMBR(Region& out) const; + virtual double getArea() const; + virtual double getMinimumDistance(const IShape& in) const; + + virtual bool intersectsRegion(const Region& in) const; + virtual bool containsRegion(const Region& in) const; + virtual bool touchesRegion(const Region& in) const; + virtual double getMinimumDistance(const Region& in) const; + + virtual bool containsPoint(const Point& in) const; + virtual bool touchesPoint(const Point& in) const; + virtual double getMinimumDistance(const Point& in) const; + + virtual Region getIntersectingRegion(const Region& r) const; + virtual double getIntersectingArea(const Region& in) const; + virtual double getMargin() const; + + virtual void combineRegion(const Region& in); + virtual void combinePoint(const Point& in); + virtual void getCombinedRegion(Region& out, const Region& in) const; + + virtual double getLow(uint32_t index) const; + virtual double getHigh(uint32_t index) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + private: + void initialize(const double* pLow, const double* pHigh, uint32_t dimension); + + public: + uint32_t m_dimension; + double* m_pLow; + double* m_pHigh; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const Region& r); + }; // Region + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const Region& r); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/SpatialIndex.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/SpatialIndex.h.svn-base new file mode 100644 index 000000000..fe6cf679b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/SpatialIndex.h.svn-base @@ -0,0 +1,250 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "tools/Tools.h" + +# if !HAVE_BZERO +# define bzero(d, n) memset((d), 0, (n)) +# endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661922 +#endif + +namespace SpatialIndex +{ + class Point; + class Region; + + typedef int64_t id_type; + + SIDX_DLL enum CommandType + { + CT_NODEREAD = 0x0, + CT_NODEDELETE, + CT_NODEWRITE + }; + + class SIDX_DLL InvalidPageException : public Tools::Exception + { + public: + InvalidPageException(id_type id); + virtual ~InvalidPageException() {} + virtual std::string what(); + + private: + std::string m_error; + }; // InvalidPageException + + // + // Interfaces + // + + class SIDX_DLL IShape : public Tools::ISerializable + { + public: + virtual bool intersectsShape(const IShape& in) const = 0; + virtual bool containsShape(const IShape& in) const = 0; + virtual bool touchesShape(const IShape& in) const = 0; + virtual void getCenter(Point& out) const = 0; + virtual uint32_t getDimension() const = 0; + virtual void getMBR(Region& out) const = 0; + virtual double getArea() const = 0; + virtual double getMinimumDistance(const IShape& in) const = 0; + virtual ~IShape() {} + }; // IShape + + class SIDX_DLL ITimeShape : public Tools::IInterval + { + public: + virtual bool intersectsShapeInTime(const ITimeShape& in) const = 0; + virtual bool intersectsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const = 0; + virtual bool containsShapeInTime(const ITimeShape& in) const = 0; + virtual bool containsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const = 0; + virtual bool touchesShapeInTime(const ITimeShape& in) const = 0; + virtual bool touchesShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const = 0; + virtual double getAreaInTime() const = 0; + virtual double getAreaInTime(const Tools::IInterval& ivI) const = 0; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const = 0; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const = 0; + virtual ~ITimeShape() {} + }; // ITimeShape + + class SIDX_DLL IEvolvingShape + { + public: + virtual void getVMBR(Region& out) const = 0; + virtual void getMBRAtTime(double t, Region& out) const = 0; + virtual ~IEvolvingShape() {} + }; // IEvolvingShape + + class SIDX_DLL IEntry : public Tools::IObject + { + public: + virtual id_type getIdentifier() const = 0; + virtual void getShape(IShape** out) const = 0; + virtual ~IEntry() {} + }; // IEntry + + class SIDX_DLL INode : public IEntry, public Tools::ISerializable + { + public: + virtual uint32_t getChildrenCount() const = 0; + virtual id_type getChildIdentifier(uint32_t index) const = 0; + virtual void getChildData(uint32_t index, uint32_t& len, byte** data) const = 0; + virtual void getChildShape(uint32_t index, IShape** out) const = 0; + virtual uint32_t getLevel() const = 0; + virtual bool isIndex() const = 0; + virtual bool isLeaf() const = 0; + virtual ~INode() {} + }; // INode + + class SIDX_DLL IData : public IEntry + { + public: + virtual void getData(uint32_t& len, byte** data) const = 0; + virtual ~IData() {} + }; // IData + + class SIDX_DLL IDataStream : public Tools::IObjectStream + { + public: + virtual IData* getNext() = 0; + virtual ~IDataStream() {} + }; // IDataStream + + class SIDX_DLL ICommand + { + public: + virtual void execute(const INode& in) = 0; + virtual ~ICommand() {} + }; // ICommand + + class SIDX_DLL INearestNeighborComparator + { + public: + virtual double getMinimumDistance(const IShape& query, const IShape& entry) = 0; + virtual double getMinimumDistance(const IShape& query, const IData& data) = 0; + virtual ~INearestNeighborComparator() {} + }; // INearestNeighborComparator + + class SIDX_DLL IStorageManager + { + public: + virtual void loadByteArray(const id_type id, uint32_t& len, byte** data) = 0; + virtual void storeByteArray(id_type& id, const uint32_t len, const byte* const data) = 0; + virtual void deleteByteArray(const id_type id) = 0; + virtual ~IStorageManager() {} + }; // IStorageManager + + class SIDX_DLL IVisitor + { + public: + virtual void visitNode(const INode& in) = 0; + virtual void visitData(const IData& in) = 0; + virtual void visitData(std::vector<const IData*>& v) = 0; + virtual ~IVisitor() {} + }; // IVisitor + + class SIDX_DLL IQueryStrategy + { + public: + virtual void getNextEntry(const IEntry& previouslyFetched, id_type& nextEntryToFetch, bool& bFetchNextEntry) = 0; + virtual ~IQueryStrategy() {} + }; // IQueryStrategy + + class SIDX_DLL IStatistics + { + public: + virtual uint64_t getReads() const = 0; + virtual uint64_t getWrites() const = 0; + virtual uint32_t getNumberOfNodes() const = 0; + virtual uint64_t getNumberOfData() const = 0; + virtual ~IStatistics() {} + }; // IStatistics + + class SIDX_DLL ISpatialIndex + { + public: + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type shapeIdentifier) = 0; + virtual bool deleteData(const IShape& shape, id_type shapeIdentifier) = 0; + virtual void containsWhatQuery(const IShape& query, IVisitor& v) = 0; + virtual void intersectsWithQuery(const IShape& query, IVisitor& v) = 0; + virtual void pointLocationQuery(const Point& query, IVisitor& v) = 0; + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) = 0; + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) = 0; + virtual void selfJoinQuery(const IShape& s, IVisitor& v) = 0; + virtual void queryStrategy(IQueryStrategy& qs) = 0; + virtual void getIndexProperties(Tools::PropertySet& out) const = 0; + virtual void addCommand(ICommand* in, CommandType ct) = 0; + virtual bool isIndexValid() = 0; + virtual void getStatistics(IStatistics** out) const = 0; + virtual ~ISpatialIndex() {} + + }; // ISpatialIndex + + namespace StorageManager + { + SIDX_DLL enum StorageManagerConstants + { + EmptyPage = -0x1, + NewPage = -0x1 + }; + + class SIDX_DLL IBuffer : public IStorageManager + { + public: + virtual uint64_t getHits() = 0; + virtual void clear() = 0; + virtual ~IBuffer() {} + }; // IBuffer + + SIDX_DLL IStorageManager* returnMemoryStorageManager(Tools::PropertySet& in); + SIDX_DLL IStorageManager* createNewMemoryStorageManager(); + + SIDX_DLL IStorageManager* returnDiskStorageManager(Tools::PropertySet& in); + SIDX_DLL IStorageManager* createNewDiskStorageManager(std::string& baseName, uint32_t pageSize); + SIDX_DLL IStorageManager* loadDiskStorageManager(std::string& baseName); + + SIDX_DLL IBuffer* returnRandomEvictionsBuffer(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL IBuffer* createNewRandomEvictionsBuffer(IStorageManager& in, uint32_t capacity, bool bWriteThrough); + } + + // + // Global functions + // + SIDX_DLL std::ostream& operator<<(std::ostream&, const ISpatialIndex&); + SIDX_DLL std::ostream& operator<<(std::ostream&, const IStatistics&); +} + +#include "Point.h" +#include "Region.h" +#include "LineSegment.h" +#include "TimePoint.h" +#include "TimeRegion.h" +#include "MovingPoint.h" +#include "MovingRegion.h" +#include "RTree.h" +#include "MVRTree.h" +#include "TPRTree.h" +#include "Version.h" diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TPRTree.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TPRTree.h.svn-base new file mode 100644 index 000000000..1af9818f9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TPRTree.h.svn-base @@ -0,0 +1,78 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + SIDX_DLL enum TPRTreeVariant + { + TPRV_RSTAR = 0x0 + }; + + SIDX_DLL enum PersistenObjectIdentifier + { + PersistentIndex = 0x1, + PersistentLeaf = 0x2 + }; + + SIDX_DLL enum RangeQueryType + { + ContainmentQuery = 0x1, + IntersectionQuery = 0x2 + }; + + class SIDX_DLL Data : public IData, public Tools::ISerializable + { + public: + Data(uint32_t len, byte* pData, MovingRegion& r, id_type id); + virtual ~Data(); + + virtual Data* clone(); + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + virtual void getData(uint32_t& len, byte** data) const; + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + id_type m_id; + MovingRegion m_region; + byte* m_pData; + uint32_t m_dataLength; + }; // Data + + SIDX_DLL ISpatialIndex* returnTPRTree(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL ISpatialIndex* createNewTPRTree( + IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + TPRTreeVariant rv, + double horizon, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* loadTPRTree(IStorageManager& in, id_type indexIdentifier); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TimePoint.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TimePoint.h.svn-base new file mode 100644 index 000000000..3d1de4e7d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TimePoint.h.svn-base @@ -0,0 +1,89 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL TimePoint : public Point, public ITimeShape + { + public: + TimePoint(); + TimePoint(const double* pCoords, const Tools::IInterval& ti, uint32_t dimension); + TimePoint(const double* pCoords, double tStart, double tEnd, uint32_t dimension); + TimePoint(const Point& p, const Tools::IInterval& ti); + TimePoint(const Point& p, double tStart, double tEnd); + TimePoint(const TimePoint& p); + virtual ~TimePoint(); + + virtual TimePoint& operator=(const TimePoint& p); + virtual bool operator==(const TimePoint& p) const; + + // + // IObject interface + // + virtual TimePoint* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // ITimeShape interface + // + virtual bool intersectsShapeInTime(const ITimeShape& in) const; + virtual bool intersectsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool containsShapeInTime(const ITimeShape& in) const; + virtual bool containsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool touchesShapeInTime(const ITimeShape& in) const; + virtual bool touchesShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual double getAreaInTime() const; + virtual double getAreaInTime(const Tools::IInterval& ivI) const; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const; + + // + // IInterval interface + // + virtual Tools::IInterval& operator=(const Tools::IInterval&); + virtual double getLowerBound() const; + virtual double getUpperBound() const; + virtual void setBounds(double, double); + virtual bool intersectsInterval(const Tools::IInterval& ti) const; + virtual bool intersectsInterval(Tools::IntervalType t, const double start, const double end) const; + virtual bool containsInterval(const Tools::IInterval& ti) const; + virtual Tools::IntervalType getIntervalType() const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + double m_startTime; + double m_endTime; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimePoint& pt); + }; // TimePoint + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimePoint& pt); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TimeRegion.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TimeRegion.h.svn-base new file mode 100644 index 000000000..46b720b45 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/TimeRegion.h.svn-base @@ -0,0 +1,102 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL TimeRegion : public Region, public ITimeShape + { + public: + TimeRegion(); + TimeRegion(const double* pLow, const double* pHigh, const Tools::IInterval& ti, uint32_t dimension); + TimeRegion(const double* pLow, const double* pHigh, double tStart, double tEnd, uint32_t dimension); + TimeRegion(const Point& low, const Point& high, const Tools::IInterval& ti); + TimeRegion(const Point& low, const Point& high, double tStart, double tEnd); + TimeRegion(const Region& in, const Tools::IInterval& ti); + TimeRegion(const Region& in, double tStart, double tEnd); + TimeRegion(const TimePoint& low, const TimePoint& high); + TimeRegion(const TimeRegion& in); + virtual ~TimeRegion(); + + virtual TimeRegion& operator=(const TimeRegion& r); + virtual bool operator==(const TimeRegion&) const; + + virtual bool intersectsRegionInTime(const TimeRegion& in) const; + virtual bool containsRegionInTime(const TimeRegion& in) const; + virtual bool touchesRegionInTime(const TimeRegion& in) const; + + virtual bool containsPointInTime(const TimePoint& in) const; + virtual bool touchesPointInTime(const TimePoint& in) const; + + virtual void combineRegionInTime(const TimeRegion& in); + virtual void getCombinedRegionInTime(TimeRegion& out, const TimeRegion& in) const; + + // + // IObject interface + // + virtual TimeRegion* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // ITimeShape interface + // + virtual bool intersectsShapeInTime(const ITimeShape& in) const; + virtual bool intersectsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool containsShapeInTime(const ITimeShape& in) const; + virtual bool containsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool touchesShapeInTime(const ITimeShape& in) const; + virtual bool touchesShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual double getAreaInTime() const; + virtual double getAreaInTime(const Tools::IInterval& ivI) const; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const; + + // + // IInterval interface + // + virtual Tools::IInterval& operator=(const Tools::IInterval&); + virtual double getLowerBound() const; + virtual double getUpperBound() const; + virtual void setBounds(double, double); + virtual bool intersectsInterval(const Tools::IInterval& ti) const; + virtual bool intersectsInterval(Tools::IntervalType t, const double start, const double end) const; + virtual bool containsInterval(const Tools::IInterval& ti) const; + virtual Tools::IntervalType getIntervalType() const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + double m_startTime; + double m_endTime; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimeRegion& r); + }; // TimeRegion + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimeRegion& r); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Version.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Version.h.svn-base new file mode 100644 index 000000000..3ecf5f687 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/.svn/text-base/Version.h.svn-base @@ -0,0 +1,42 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#ifndef SIDX_VERSION_MAJOR +#define SIDX_VERSION_MAJOR 1 +#define SIDX_VERSION_MINOR 6 +#define SIDX_VERSION_REV 1 +#define SIDX_VERSION_BUILD 0 +#endif + +#ifndef SIDX_VERSION_NUM +#define SIDX_VERSION_NUM (SIDX_VERSION_MAJOR*1000+SIDX_VERSION_MINOR*100+SIDX_VERSION_REV*10+SIDX_VERSION_BUILD) +#endif + +#ifndef SIDX_RELEASE_DATE +#define SIDX_RELEASE_DATE 20101204 +#endif + +#ifndef SIDX_RELEASE_NAME +#define SIDX_RELEASE_NAME "1.6.1" +#endif + diff --git a/sci-libs/libspatialindex/svn/trunk/include/LineSegment.h b/sci-libs/libspatialindex/svn/trunk/include/LineSegment.h new file mode 100644 index 000000000..ab09e5291 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/LineSegment.h @@ -0,0 +1,83 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL LineSegment : public Tools::IObject, public virtual IShape + { + public: + LineSegment(); + LineSegment(const double* startPoint, const double* endPoint, uint32_t dimension); + LineSegment(const Point& startPoint, const Point& endPoint); + LineSegment(const LineSegment& l); + virtual ~LineSegment(); + + virtual LineSegment& operator=(const LineSegment& p); + virtual bool operator==(const LineSegment& p) const; + + // + // IObject interface + // + virtual LineSegment* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& length); + + // + // IShape interface + // + virtual bool intersectsShape(const IShape& in) const; + virtual bool containsShape(const IShape& in) const; + virtual bool touchesShape(const IShape& in) const; + virtual void getCenter(Point& out) const; + virtual uint32_t getDimension() const; + virtual void getMBR(Region& out) const; + virtual double getArea() const; + virtual double getMinimumDistance(const IShape& in) const; + + virtual double getMinimumDistance(const Point& p) const; + //virtual double getMinimumDistance(const Region& r) const; + virtual double getRelativeMinimumDistance(const Point& p) const; + virtual double getRelativeMaximumDistance(const Region& r) const; + virtual double getAngleOfPerpendicularRay(); + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + uint32_t m_dimension; + double* m_pStartPoint; + double* m_pEndPoint; + + friend class Region; + friend class Point; + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const LineSegment& pt); + }; // Point + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const LineSegment& pt); +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/MVRTree.h b/sci-libs/libspatialindex/svn/trunk/include/MVRTree.h new file mode 100644 index 000000000..aa1aeaab5 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/MVRTree.h @@ -0,0 +1,83 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + SIDX_DLL enum MVRTreeVariant + { + RV_LINEAR = 0x0, + RV_QUADRATIC, + RV_RSTAR + }; + + SIDX_DLL enum PersistenObjectIdentifier + { + PersistentIndex = 0x1, + PersistentLeaf = 0x2 + }; + + SIDX_DLL enum RangeQueryType + { + ContainmentQuery = 0x1, + IntersectionQuery = 0x2 + }; + + class SIDX_DLL Data : public IData, public Tools::ISerializable + { + public: + Data(uint32_t len, byte* pData, TimeRegion& r, id_type id); + virtual ~Data(); + + virtual Data* clone(); + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + virtual void getData(uint32_t& len, byte** data) const; + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + id_type m_id; + TimeRegion m_region; + byte* m_pData; + uint32_t m_dataLength; + }; // Data + + SIDX_DLL ISpatialIndex* returnMVRTree(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL ISpatialIndex* createNewMVRTree( + IStorageManager& in, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + MVRTreeVariant rv, + id_type& out_indexIdentifier + ); + SIDX_DLL ISpatialIndex* loadMVRTree( + IStorageManager& in, + id_type indexIdentifier + ); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/Makefile.am b/sci-libs/libspatialindex/svn/trunk/include/Makefile.am new file mode 100644 index 000000000..e061275ce --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = tools capi + +spatialindexdir = $(includedir)/spatialindex + +spatialindex_HEADERS = SpatialIndex.h \ + RTree.h \ + MVRTree.h \ + TPRTree.h \ + Point.h \ + Region.h \ + LineSegment.h \ + TimePoint.h \ + TimeRegion.h \ + MovingPoint.h \ + MovingRegion.h \ + Version.h
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/include/MovingPoint.h b/sci-libs/libspatialindex/svn/trunk/include/MovingPoint.h new file mode 100644 index 000000000..bca600a5b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/MovingPoint.h @@ -0,0 +1,79 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL MovingPoint : public TimePoint, public IEvolvingShape + { + public: + MovingPoint(); + MovingPoint(const double* pCoords, const double* pVCoords, const Tools::IInterval& ti, uint32_t dimension); + MovingPoint(const double* pCoords, const double* pVCoords, double tStart, double tEnd, uint32_t dimension); + MovingPoint(const Point& p, const Point& vp, const Tools::IInterval& ti); + MovingPoint(const Point& p, const Point& vp, double tStart, double tEnd); + MovingPoint(const MovingPoint& p); + virtual ~MovingPoint(); + + virtual MovingPoint& operator=(const MovingPoint& p); + virtual bool operator==(const MovingPoint& p) const; + + virtual double getCoord(uint32_t index, double t) const; + virtual double getProjectedCoord(uint32_t index, double t) const; + virtual double getVCoord(uint32_t index) const; + virtual void getPointAtTime(double t, Point& out) const; + + // + // IObject interface + // + virtual MovingPoint* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // IEvolvingShape interface + // + virtual void getVMBR(Region& out) const; + virtual void getMBRAtTime(double t, Region& out) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + private: + void initialize( + const double* pCoords, const double* pVCoords, + double tStart, double tEnd, uint32_t dimension); + + public: + double* m_pVCoords; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingPoint& pt); + }; // MovingPoint + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingPoint& pt); +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/MovingRegion.h b/sci-libs/libspatialindex/svn/trunk/include/MovingRegion.h new file mode 100644 index 000000000..d25c50688 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/MovingRegion.h @@ -0,0 +1,155 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL MovingRegion : public TimeRegion, public IEvolvingShape + { + public: + MovingRegion(); + MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + const Tools::IInterval& ti, uint32_t dimension); + MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension); + MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + const Tools::IInterval& ti); + MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + double tStart, double tEnd); + MovingRegion(const Region& mbr, const Region& vbr, const Tools::IInterval& ivI); + MovingRegion(const Region& mbr, const Region& vbr, double tStart, double tEnd); + MovingRegion(const MovingPoint& low, const MovingPoint& high); + MovingRegion(const MovingRegion& in); + virtual ~MovingRegion(); + + virtual MovingRegion& operator=(const MovingRegion& r); + virtual bool operator==(const MovingRegion&) const; + + bool isShrinking() const; + + virtual double getLow(uint32_t index, double t) const; + virtual double getHigh(uint32_t index, double t) const; + virtual double getExtrapolatedLow(uint32_t index, double t) const; + virtual double getExtrapolatedHigh(uint32_t index, double t) const; + virtual double getVLow(uint32_t index) const; + virtual double getVHigh(uint32_t index) const; + + virtual bool intersectsRegionInTime(const MovingRegion& r) const; + virtual bool intersectsRegionInTime(const MovingRegion& r, Tools::IInterval& out) const; + virtual bool intersectsRegionInTime(const Tools::IInterval& ivI, const MovingRegion& r, Tools::IInterval& ret) const; + virtual bool containsRegionInTime(const MovingRegion& r) const; + virtual bool containsRegionInTime(const Tools::IInterval& ivI, const MovingRegion& r) const; + virtual bool containsRegionAfterTime(double t, const MovingRegion& r) const; + + virtual double getProjectedSurfaceAreaInTime() const; + virtual double getProjectedSurfaceAreaInTime(const Tools::IInterval& ivI) const; + + virtual double getCenterDistanceInTime(const MovingRegion& r) const; + virtual double getCenterDistanceInTime(const Tools::IInterval& ivI, const MovingRegion& r) const; + + virtual bool intersectsRegionAtTime(double t, const MovingRegion& r) const; + virtual bool containsRegionAtTime(double t, const MovingRegion& r) const; + + virtual bool intersectsPointInTime(const MovingPoint& p) const; + virtual bool intersectsPointInTime(const MovingPoint& p, Tools::IInterval& out) const; + virtual bool intersectsPointInTime(const Tools::IInterval& ivI, const MovingPoint& p, Tools::IInterval& out) const; + virtual bool containsPointInTime(const MovingPoint& p) const; + virtual bool containsPointInTime(const Tools::IInterval& ivI, const MovingPoint& p) const; + + //virtual bool intersectsPointAtTime(double t, const MovingRegion& in) const; + //virtual bool containsPointAtTime(double t, const MovingRegion& in) const; + + virtual void combineRegionInTime(const MovingRegion& r); + virtual void combineRegionAfterTime(double t, const MovingRegion& r); + virtual void getCombinedRegionInTime(MovingRegion& out, const MovingRegion& in) const; + virtual void getCombinedRegionAfterTime(double t, MovingRegion& out, const MovingRegion& in) const; + + virtual double getIntersectingAreaInTime(const MovingRegion& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const MovingRegion& r) const; + + // + // IObject interface + // + virtual MovingRegion* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // IEvolvingShape interface + // + virtual void getVMBR(Region& out) const; + virtual void getMBRAtTime(double t, Region& out) const; + + // + // ITimeShape interface + // + virtual double getAreaInTime() const; + virtual double getAreaInTime(const Tools::IInterval& ivI) const; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + private: + void initialize( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension); + + public: + class CrossPoint + { + public: + double m_t; + uint32_t m_dimension; + uint32_t m_boundary; + const MovingRegion* m_to; + + struct ascending: public std::binary_function<CrossPoint&, CrossPoint&, bool> + { + bool operator()(const CrossPoint& __x, const CrossPoint& __y) const { return __x.m_t > __y.m_t; } + }; + }; // CrossPoint + + public: + double* m_pVLow; + double* m_pVHigh; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingRegion& r); + }; // MovingRegion + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const MovingRegion& r); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/Point.h b/sci-libs/libspatialindex/svn/trunk/include/Point.h new file mode 100644 index 000000000..51cb4b618 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/Point.h @@ -0,0 +1,77 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL Point : public Tools::IObject, public virtual IShape + { + public: + Point(); + Point(const double* pCoords, uint32_t dimension); + Point(const Point& p); + virtual ~Point(); + + virtual Point& operator=(const Point& p); + virtual bool operator==(const Point& p) const; + + // + // IObject interface + // + virtual Point* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& length); + + // + // IShape interface + // + virtual bool intersectsShape(const IShape& in) const; + virtual bool containsShape(const IShape& in) const; + virtual bool touchesShape(const IShape& in) const; + virtual void getCenter(Point& out) const; + virtual uint32_t getDimension() const; + virtual void getMBR(Region& out) const; + virtual double getArea() const; + virtual double getMinimumDistance(const IShape& in) const; + + virtual double getMinimumDistance(const Point& p) const; + + virtual double getCoordinate(uint32_t index) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + uint32_t m_dimension; + double* m_pCoords; + + friend class Region; + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const Point& pt); + }; // Point + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const Point& pt); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/RTree.h b/sci-libs/libspatialindex/svn/trunk/include/RTree.h new file mode 100644 index 000000000..4303b9e96 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/RTree.h @@ -0,0 +1,102 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + SIDX_DLL enum RTreeVariant + { + RV_LINEAR = 0x0, + RV_QUADRATIC, + RV_RSTAR + }; + + SIDX_DLL enum BulkLoadMethod + { + BLM_STR = 0x0 + }; + + SIDX_DLL enum PersistenObjectIdentifier + { + PersistentIndex = 0x1, + PersistentLeaf = 0x2 + }; + + SIDX_DLL enum RangeQueryType + { + ContainmentQuery = 0x1, + IntersectionQuery = 0x2 + }; + + class SIDX_DLL Data : public IData, public Tools::ISerializable + { + public: + Data(uint32_t len, byte* pData, Region& r, id_type id); + virtual ~Data(); + + virtual Data* clone(); + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + virtual void getData(uint32_t& len, byte** data) const; + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + id_type m_id; + Region m_region; + byte* m_pData; + uint32_t m_dataLength; + }; // Data + + SIDX_DLL ISpatialIndex* returnRTree(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL ISpatialIndex* createNewRTree( + IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + RTreeVariant rv, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + RTreeVariant rv, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + IStorageManager& sm, + Tools::PropertySet& ps, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* loadRTree(IStorageManager& in, id_type indexIdentifier); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/Region.h b/sci-libs/libspatialindex/svn/trunk/include/Region.h new file mode 100644 index 000000000..feddaee10 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/Region.h @@ -0,0 +1,97 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL Region : public Tools::IObject, public virtual IShape + { + public: + Region(); + Region(const double* pLow, const double* pHigh, uint32_t dimension); + Region(const Point& low, const Point& high); + Region(const Region& in); + virtual ~Region(); + + virtual Region& operator=(const Region& r); + virtual bool operator==(const Region&) const; + + // + // IObject interface + // + virtual Region* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& length); + + // + // IShape interface + // + virtual bool intersectsShape(const IShape& in) const; + virtual bool containsShape(const IShape& in) const; + virtual bool touchesShape(const IShape& in) const; + virtual void getCenter(Point& out) const; + virtual uint32_t getDimension() const; + virtual void getMBR(Region& out) const; + virtual double getArea() const; + virtual double getMinimumDistance(const IShape& in) const; + + virtual bool intersectsRegion(const Region& in) const; + virtual bool containsRegion(const Region& in) const; + virtual bool touchesRegion(const Region& in) const; + virtual double getMinimumDistance(const Region& in) const; + + virtual bool containsPoint(const Point& in) const; + virtual bool touchesPoint(const Point& in) const; + virtual double getMinimumDistance(const Point& in) const; + + virtual Region getIntersectingRegion(const Region& r) const; + virtual double getIntersectingArea(const Region& in) const; + virtual double getMargin() const; + + virtual void combineRegion(const Region& in); + virtual void combinePoint(const Point& in); + virtual void getCombinedRegion(Region& out, const Region& in) const; + + virtual double getLow(uint32_t index) const; + virtual double getHigh(uint32_t index) const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + private: + void initialize(const double* pLow, const double* pHigh, uint32_t dimension); + + public: + uint32_t m_dimension; + double* m_pLow; + double* m_pHigh; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const Region& r); + }; // Region + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const Region& r); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/SpatialIndex.h b/sci-libs/libspatialindex/svn/trunk/include/SpatialIndex.h new file mode 100644 index 000000000..fe6cf679b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/SpatialIndex.h @@ -0,0 +1,250 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "tools/Tools.h" + +# if !HAVE_BZERO +# define bzero(d, n) memset((d), 0, (n)) +# endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661922 +#endif + +namespace SpatialIndex +{ + class Point; + class Region; + + typedef int64_t id_type; + + SIDX_DLL enum CommandType + { + CT_NODEREAD = 0x0, + CT_NODEDELETE, + CT_NODEWRITE + }; + + class SIDX_DLL InvalidPageException : public Tools::Exception + { + public: + InvalidPageException(id_type id); + virtual ~InvalidPageException() {} + virtual std::string what(); + + private: + std::string m_error; + }; // InvalidPageException + + // + // Interfaces + // + + class SIDX_DLL IShape : public Tools::ISerializable + { + public: + virtual bool intersectsShape(const IShape& in) const = 0; + virtual bool containsShape(const IShape& in) const = 0; + virtual bool touchesShape(const IShape& in) const = 0; + virtual void getCenter(Point& out) const = 0; + virtual uint32_t getDimension() const = 0; + virtual void getMBR(Region& out) const = 0; + virtual double getArea() const = 0; + virtual double getMinimumDistance(const IShape& in) const = 0; + virtual ~IShape() {} + }; // IShape + + class SIDX_DLL ITimeShape : public Tools::IInterval + { + public: + virtual bool intersectsShapeInTime(const ITimeShape& in) const = 0; + virtual bool intersectsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const = 0; + virtual bool containsShapeInTime(const ITimeShape& in) const = 0; + virtual bool containsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const = 0; + virtual bool touchesShapeInTime(const ITimeShape& in) const = 0; + virtual bool touchesShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const = 0; + virtual double getAreaInTime() const = 0; + virtual double getAreaInTime(const Tools::IInterval& ivI) const = 0; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const = 0; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const = 0; + virtual ~ITimeShape() {} + }; // ITimeShape + + class SIDX_DLL IEvolvingShape + { + public: + virtual void getVMBR(Region& out) const = 0; + virtual void getMBRAtTime(double t, Region& out) const = 0; + virtual ~IEvolvingShape() {} + }; // IEvolvingShape + + class SIDX_DLL IEntry : public Tools::IObject + { + public: + virtual id_type getIdentifier() const = 0; + virtual void getShape(IShape** out) const = 0; + virtual ~IEntry() {} + }; // IEntry + + class SIDX_DLL INode : public IEntry, public Tools::ISerializable + { + public: + virtual uint32_t getChildrenCount() const = 0; + virtual id_type getChildIdentifier(uint32_t index) const = 0; + virtual void getChildData(uint32_t index, uint32_t& len, byte** data) const = 0; + virtual void getChildShape(uint32_t index, IShape** out) const = 0; + virtual uint32_t getLevel() const = 0; + virtual bool isIndex() const = 0; + virtual bool isLeaf() const = 0; + virtual ~INode() {} + }; // INode + + class SIDX_DLL IData : public IEntry + { + public: + virtual void getData(uint32_t& len, byte** data) const = 0; + virtual ~IData() {} + }; // IData + + class SIDX_DLL IDataStream : public Tools::IObjectStream + { + public: + virtual IData* getNext() = 0; + virtual ~IDataStream() {} + }; // IDataStream + + class SIDX_DLL ICommand + { + public: + virtual void execute(const INode& in) = 0; + virtual ~ICommand() {} + }; // ICommand + + class SIDX_DLL INearestNeighborComparator + { + public: + virtual double getMinimumDistance(const IShape& query, const IShape& entry) = 0; + virtual double getMinimumDistance(const IShape& query, const IData& data) = 0; + virtual ~INearestNeighborComparator() {} + }; // INearestNeighborComparator + + class SIDX_DLL IStorageManager + { + public: + virtual void loadByteArray(const id_type id, uint32_t& len, byte** data) = 0; + virtual void storeByteArray(id_type& id, const uint32_t len, const byte* const data) = 0; + virtual void deleteByteArray(const id_type id) = 0; + virtual ~IStorageManager() {} + }; // IStorageManager + + class SIDX_DLL IVisitor + { + public: + virtual void visitNode(const INode& in) = 0; + virtual void visitData(const IData& in) = 0; + virtual void visitData(std::vector<const IData*>& v) = 0; + virtual ~IVisitor() {} + }; // IVisitor + + class SIDX_DLL IQueryStrategy + { + public: + virtual void getNextEntry(const IEntry& previouslyFetched, id_type& nextEntryToFetch, bool& bFetchNextEntry) = 0; + virtual ~IQueryStrategy() {} + }; // IQueryStrategy + + class SIDX_DLL IStatistics + { + public: + virtual uint64_t getReads() const = 0; + virtual uint64_t getWrites() const = 0; + virtual uint32_t getNumberOfNodes() const = 0; + virtual uint64_t getNumberOfData() const = 0; + virtual ~IStatistics() {} + }; // IStatistics + + class SIDX_DLL ISpatialIndex + { + public: + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type shapeIdentifier) = 0; + virtual bool deleteData(const IShape& shape, id_type shapeIdentifier) = 0; + virtual void containsWhatQuery(const IShape& query, IVisitor& v) = 0; + virtual void intersectsWithQuery(const IShape& query, IVisitor& v) = 0; + virtual void pointLocationQuery(const Point& query, IVisitor& v) = 0; + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) = 0; + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) = 0; + virtual void selfJoinQuery(const IShape& s, IVisitor& v) = 0; + virtual void queryStrategy(IQueryStrategy& qs) = 0; + virtual void getIndexProperties(Tools::PropertySet& out) const = 0; + virtual void addCommand(ICommand* in, CommandType ct) = 0; + virtual bool isIndexValid() = 0; + virtual void getStatistics(IStatistics** out) const = 0; + virtual ~ISpatialIndex() {} + + }; // ISpatialIndex + + namespace StorageManager + { + SIDX_DLL enum StorageManagerConstants + { + EmptyPage = -0x1, + NewPage = -0x1 + }; + + class SIDX_DLL IBuffer : public IStorageManager + { + public: + virtual uint64_t getHits() = 0; + virtual void clear() = 0; + virtual ~IBuffer() {} + }; // IBuffer + + SIDX_DLL IStorageManager* returnMemoryStorageManager(Tools::PropertySet& in); + SIDX_DLL IStorageManager* createNewMemoryStorageManager(); + + SIDX_DLL IStorageManager* returnDiskStorageManager(Tools::PropertySet& in); + SIDX_DLL IStorageManager* createNewDiskStorageManager(std::string& baseName, uint32_t pageSize); + SIDX_DLL IStorageManager* loadDiskStorageManager(std::string& baseName); + + SIDX_DLL IBuffer* returnRandomEvictionsBuffer(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL IBuffer* createNewRandomEvictionsBuffer(IStorageManager& in, uint32_t capacity, bool bWriteThrough); + } + + // + // Global functions + // + SIDX_DLL std::ostream& operator<<(std::ostream&, const ISpatialIndex&); + SIDX_DLL std::ostream& operator<<(std::ostream&, const IStatistics&); +} + +#include "Point.h" +#include "Region.h" +#include "LineSegment.h" +#include "TimePoint.h" +#include "TimeRegion.h" +#include "MovingPoint.h" +#include "MovingRegion.h" +#include "RTree.h" +#include "MVRTree.h" +#include "TPRTree.h" +#include "Version.h" diff --git a/sci-libs/libspatialindex/svn/trunk/include/TPRTree.h b/sci-libs/libspatialindex/svn/trunk/include/TPRTree.h new file mode 100644 index 000000000..1af9818f9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/TPRTree.h @@ -0,0 +1,78 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + SIDX_DLL enum TPRTreeVariant + { + TPRV_RSTAR = 0x0 + }; + + SIDX_DLL enum PersistenObjectIdentifier + { + PersistentIndex = 0x1, + PersistentLeaf = 0x2 + }; + + SIDX_DLL enum RangeQueryType + { + ContainmentQuery = 0x1, + IntersectionQuery = 0x2 + }; + + class SIDX_DLL Data : public IData, public Tools::ISerializable + { + public: + Data(uint32_t len, byte* pData, MovingRegion& r, id_type id); + virtual ~Data(); + + virtual Data* clone(); + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + virtual void getData(uint32_t& len, byte** data) const; + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + id_type m_id; + MovingRegion m_region; + byte* m_pData; + uint32_t m_dataLength; + }; // Data + + SIDX_DLL ISpatialIndex* returnTPRTree(IStorageManager& ind, Tools::PropertySet& in); + SIDX_DLL ISpatialIndex* createNewTPRTree( + IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + TPRTreeVariant rv, + double horizon, + id_type& indexIdentifier + ); + SIDX_DLL ISpatialIndex* loadTPRTree(IStorageManager& in, id_type indexIdentifier); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/TimePoint.h b/sci-libs/libspatialindex/svn/trunk/include/TimePoint.h new file mode 100644 index 000000000..3d1de4e7d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/TimePoint.h @@ -0,0 +1,89 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL TimePoint : public Point, public ITimeShape + { + public: + TimePoint(); + TimePoint(const double* pCoords, const Tools::IInterval& ti, uint32_t dimension); + TimePoint(const double* pCoords, double tStart, double tEnd, uint32_t dimension); + TimePoint(const Point& p, const Tools::IInterval& ti); + TimePoint(const Point& p, double tStart, double tEnd); + TimePoint(const TimePoint& p); + virtual ~TimePoint(); + + virtual TimePoint& operator=(const TimePoint& p); + virtual bool operator==(const TimePoint& p) const; + + // + // IObject interface + // + virtual TimePoint* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // ITimeShape interface + // + virtual bool intersectsShapeInTime(const ITimeShape& in) const; + virtual bool intersectsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool containsShapeInTime(const ITimeShape& in) const; + virtual bool containsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool touchesShapeInTime(const ITimeShape& in) const; + virtual bool touchesShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual double getAreaInTime() const; + virtual double getAreaInTime(const Tools::IInterval& ivI) const; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const; + + // + // IInterval interface + // + virtual Tools::IInterval& operator=(const Tools::IInterval&); + virtual double getLowerBound() const; + virtual double getUpperBound() const; + virtual void setBounds(double, double); + virtual bool intersectsInterval(const Tools::IInterval& ti) const; + virtual bool intersectsInterval(Tools::IntervalType t, const double start, const double end) const; + virtual bool containsInterval(const Tools::IInterval& ti) const; + virtual Tools::IntervalType getIntervalType() const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + double m_startTime; + double m_endTime; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimePoint& pt); + }; // TimePoint + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimePoint& pt); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/TimeRegion.h b/sci-libs/libspatialindex/svn/trunk/include/TimeRegion.h new file mode 100644 index 000000000..46b720b45 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/TimeRegion.h @@ -0,0 +1,102 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + class SIDX_DLL TimeRegion : public Region, public ITimeShape + { + public: + TimeRegion(); + TimeRegion(const double* pLow, const double* pHigh, const Tools::IInterval& ti, uint32_t dimension); + TimeRegion(const double* pLow, const double* pHigh, double tStart, double tEnd, uint32_t dimension); + TimeRegion(const Point& low, const Point& high, const Tools::IInterval& ti); + TimeRegion(const Point& low, const Point& high, double tStart, double tEnd); + TimeRegion(const Region& in, const Tools::IInterval& ti); + TimeRegion(const Region& in, double tStart, double tEnd); + TimeRegion(const TimePoint& low, const TimePoint& high); + TimeRegion(const TimeRegion& in); + virtual ~TimeRegion(); + + virtual TimeRegion& operator=(const TimeRegion& r); + virtual bool operator==(const TimeRegion&) const; + + virtual bool intersectsRegionInTime(const TimeRegion& in) const; + virtual bool containsRegionInTime(const TimeRegion& in) const; + virtual bool touchesRegionInTime(const TimeRegion& in) const; + + virtual bool containsPointInTime(const TimePoint& in) const; + virtual bool touchesPointInTime(const TimePoint& in) const; + + virtual void combineRegionInTime(const TimeRegion& in); + virtual void getCombinedRegionInTime(TimeRegion& out, const TimeRegion& in) const; + + // + // IObject interface + // + virtual TimeRegion* clone(); + + // + // ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // ITimeShape interface + // + virtual bool intersectsShapeInTime(const ITimeShape& in) const; + virtual bool intersectsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool containsShapeInTime(const ITimeShape& in) const; + virtual bool containsShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual bool touchesShapeInTime(const ITimeShape& in) const; + virtual bool touchesShapeInTime(const Tools::IInterval& ivI, const ITimeShape& in) const; + virtual double getAreaInTime() const; + virtual double getAreaInTime(const Tools::IInterval& ivI) const; + virtual double getIntersectingAreaInTime(const ITimeShape& r) const; + virtual double getIntersectingAreaInTime(const Tools::IInterval& ivI, const ITimeShape& r) const; + + // + // IInterval interface + // + virtual Tools::IInterval& operator=(const Tools::IInterval&); + virtual double getLowerBound() const; + virtual double getUpperBound() const; + virtual void setBounds(double, double); + virtual bool intersectsInterval(const Tools::IInterval& ti) const; + virtual bool intersectsInterval(Tools::IntervalType t, const double start, const double end) const; + virtual bool containsInterval(const Tools::IInterval& ti) const; + virtual Tools::IntervalType getIntervalType() const; + + virtual void makeInfinite(uint32_t dimension); + virtual void makeDimension(uint32_t dimension); + + public: + double m_startTime; + double m_endTime; + + friend SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimeRegion& r); + }; // TimeRegion + + SIDX_DLL std::ostream& operator<<(std::ostream& os, const TimeRegion& r); +} diff --git a/sci-libs/libspatialindex/svn/trunk/include/Version.h b/sci-libs/libspatialindex/svn/trunk/include/Version.h new file mode 100644 index 000000000..3ecf5f687 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/Version.h @@ -0,0 +1,42 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#ifndef SIDX_VERSION_MAJOR +#define SIDX_VERSION_MAJOR 1 +#define SIDX_VERSION_MINOR 6 +#define SIDX_VERSION_REV 1 +#define SIDX_VERSION_BUILD 0 +#endif + +#ifndef SIDX_VERSION_NUM +#define SIDX_VERSION_NUM (SIDX_VERSION_MAJOR*1000+SIDX_VERSION_MINOR*100+SIDX_VERSION_REV*10+SIDX_VERSION_BUILD) +#endif + +#ifndef SIDX_RELEASE_DATE +#define SIDX_RELEASE_DATE 20101204 +#endif + +#ifndef SIDX_RELEASE_NAME +#define SIDX_RELEASE_NAME "1.6.1" +#endif + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/all-wcprops new file mode 100644 index 000000000..58b86056f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/all-wcprops @@ -0,0 +1,89 @@ +K 25 +svn:wc:ra_dav:version-url +V 58 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi +END +Error.h +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/138/spatialindex/trunk/include/capi/Error.h +END +ObjVisitor.h +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/172/spatialindex/trunk/include/capi/ObjVisitor.h +END +IdVisitor.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/172/spatialindex/trunk/include/capi/IdVisitor.h +END +sidx_config.h +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi/sidx_config.h +END +LeafQuery.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/145/spatialindex/trunk/include/capi/LeafQuery.h +END +CustomStorage.h +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi/CustomStorage.h +END +BoundsQuery.h +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/138/spatialindex/trunk/include/capi/BoundsQuery.h +END +sidx_api.h +K 25 +svn:wc:ra_dav:version-url +V 69 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi/sidx_api.h +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi/Makefile.am +END +Utility.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/138/spatialindex/trunk/include/capi/Utility.h +END +DataStream.h +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/138/spatialindex/trunk/include/capi/DataStream.h +END +Index.h +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi/Index.h +END +CountVisitor.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/spatialindex/!svn/ver/173/spatialindex/trunk/include/capi/CountVisitor.h +END +sidx_impl.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/186/spatialindex/trunk/include/capi/sidx_impl.h +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/dir-prop-base new file mode 100644 index 000000000..a57f5442b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 21 +Makefile +Makefile.in + +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/entries b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/entries new file mode 100644 index 000000000..8f2ebbd0c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/entries @@ -0,0 +1,504 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/include/capi +http://svn.gispython.org/spatialindex + + + +2010-06-19T20:34:19.329614Z +186 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Error.h +file + + + + +2011-08-01T00:42:34.309378Z +05b09bc45890b74bc65c8caa0fc3fbe5 +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +1786 + +ObjVisitor.h +file + + + + +2011-08-01T00:42:34.309378Z +272e39b06c1b8b9c61a6e6f282e6e5e3 +2010-03-03T21:55:09.207890Z +172 +hobu + + + + + + + + + + + + + + + + + + + + + +1787 + +IdVisitor.h +file + + + + +2011-08-01T00:42:34.309378Z +5334daab2cd686d7dfc3baeb20d3a6ce +2010-03-03T21:55:09.207890Z +172 +hobu + + + + + + + + + + + + + + + + + + + + + +1751 + +sidx_config.h +file + + + + +2011-08-01T00:42:34.309378Z +105ee8687b2829f08473a8a0badfcc82 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +2866 + +LeafQuery.h +file + + + + +2011-08-01T00:42:34.309378Z +5e44029672cef4bc0c31072218b80d94 +2009-09-17T20:40:25.584745Z +145 +hobu + + + + + + + + + + + + + + + + + + + + + +2499 + +CustomStorage.h +file + + + + +2011-08-01T00:42:34.309378Z +1033a25bfcdcca8968bdb5b81088b03d +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +3153 + +BoundsQuery.h +file + + + + +2011-08-01T00:42:34.309378Z +303f7d59f62a452a312c3acc1d757c4e +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +1728 + +sidx_api.h +file + + + + +2011-08-01T00:42:34.321137Z +f035d9a6d98a51c0a8d033d71e48eb23 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +8592 + +Makefile.am +file + + + + +2011-08-01T00:42:34.321137Z +cbe5fb6149f497314f16b3145ca76f3d +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +368 + +Utility.h +file + + + + +2011-08-01T00:42:34.321137Z +cb8761d7dc01f8ffa518db4aebd8fc12 +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +1324 + +DataStream.h +file + + + + +2011-08-01T00:42:34.321137Z +e73f67a514dd56ce697e8e5c7ab2b062 +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +2046 + +Index.h +file + + + + +2011-08-01T00:42:34.321137Z +d7808f62d2ad6851b808e587553686b7 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +2530 + +CountVisitor.h +file + + + + +2011-08-01T00:42:34.321137Z +f5c5acacea25040af7e548cd9ee23c91 +2010-03-04T16:33:28.494647Z +173 +hobu + + + + + + + + + + + + + + + + + + + + + +1592 + +sidx_impl.h +file + + + + +2011-08-01T00:42:34.321137Z +9bda93160a69daca518d4a5381b0f273 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +1708 + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/BoundsQuery.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/BoundsQuery.h.svn-base new file mode 100644 index 000000000..42fa6582a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/BoundsQuery.h.svn-base @@ -0,0 +1,45 @@ +/****************************************************************************** + * $Id: boundsquery.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the bounds query. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class BoundsQuery : public SpatialIndex::IQueryStrategy +{ +private: + SpatialIndex::Region* m_bounds; + +public: + + BoundsQuery(); + ~BoundsQuery() { if (m_bounds !=0) delete m_bounds;} + void getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext); + + SpatialIndex::Region* GetBounds() const {return m_bounds; } +}; + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/CountVisitor.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/CountVisitor.h.svn-base new file mode 100644 index 000000000..323f90aa9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/CountVisitor.h.svn-base @@ -0,0 +1,45 @@ +/****************************************************************************** +* $Id$ +* +* Project: libsidx - A C API wrapper around libspatialindex +* Purpose: C++ objects to implement the count visitor. +* Author: Leonard Norrgård, leonard.norrgard@refactor.fi +* +****************************************************************************** +* Copyright (c) 2010, Leonard Norrgård +* +* All rights reserved. +* +* This library is free software; you can redistribute it and/or modify it under +* the terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; either version 2.1 of the License, or (at your option) +* any later version. + +* This library is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +* details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this library; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#pragma once + +class CountVisitor : public SpatialIndex::IVisitor +{ +private: + uint64_t nResults; + +public: + + CountVisitor(); + ~CountVisitor(); + + uint64_t GetResultCount() const { return nResults; } + + void visitNode(const SpatialIndex::INode& n); + void visitData(const SpatialIndex::IData& d); + void visitData(std::vector<const SpatialIndex::IData*>& v); +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/CustomStorage.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/CustomStorage.h.svn-base new file mode 100644 index 000000000..35f208273 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/CustomStorage.h.svn-base @@ -0,0 +1,73 @@ +/****************************************************************************** + * $Id: CustomStorage.h 1385 2009-06-17 13:45:16Z nitro $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the custom storage manager. + * Author: Matthias (nitro) + * + ****************************************************************************** + * Copyright (c) 2010, Matthias (nitro) + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +namespace SpatialIndex +{ + namespace StorageManager + { + struct CustomStorageManagerCallbacks + { + CustomStorageManagerCallbacks() : context(0), createCallback(0), destroyCallback(0), loadByteArrayCallback(0), storeByteArrayCallback(0), deleteByteArrayCallback(0) + {} + + void* context; + void (*createCallback)( const void* context, int* errorCode ); + void (*destroyCallback)( const void* context, int* errorCode ); + void (*loadByteArrayCallback)( const void* context, const id_type page, uint32_t* len, byte** data, int* errorCode ); + void (*storeByteArrayCallback)( const void* context, id_type* page, const uint32_t len, const byte* const data, int* errorCode ); + void (*deleteByteArrayCallback)( const void* context, const id_type page, int* errorCode ); + }; + + class CustomStorageManager : public SpatialIndex::IStorageManager + { + public: + // I'd like this to be an enum, but casting between enums and ints is not nice + static const int NoError = 0; + static const int InvalidPageError = 1; + static const int IllegalStateError = 2; + + CustomStorageManager(Tools::PropertySet&); + + virtual ~CustomStorageManager(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + private: + CustomStorageManagerCallbacks callbacks; + + inline void processErrorCode(int errorCode, const id_type page); + }; // CustomStorageManager + + // factory function + IStorageManager* returnCustomStorageManager(Tools::PropertySet& in); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/DataStream.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/DataStream.h.svn-base new file mode 100644 index 000000000..93a7f12a6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/DataStream.h.svn-base @@ -0,0 +1,53 @@ +/****************************************************************************** + * $Id: datastream.hpp 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the datastream. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class DataStream : public SpatialIndex::IDataStream +{ +public: + DataStream(int (*readNext)(SpatialIndex::id_type* id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength)); + ~DataStream(); + + SpatialIndex::IData* getNext(); + bool hasNext() throw (Tools::NotSupportedException); + + uint32_t size() throw (Tools::NotSupportedException); + void rewind() throw (Tools::NotSupportedException); + +protected: + SpatialIndex::RTree::Data* m_pNext; + SpatialIndex::id_type m_id; + +private: + int (*iterfunct)(SpatialIndex::id_type *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength); + + bool readData(); + bool m_bDoneReading; + +}; + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Error.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Error.h.svn-base new file mode 100644 index 000000000..69d805d44 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Error.h.svn-base @@ -0,0 +1,51 @@ +/****************************************************************************** + * $Id: error.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the error object. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class Error +{ +public: + + Error(int code, std::string const& message, std::string const& method); + + /// Copy constructor. + Error(Error const& other); + + /// Assignment operator. + Error& operator=(Error const& rhs); + + int GetCode() const { return m_code; }; + const char* GetMessage() const { return m_message.c_str(); }; + const char* GetMethod() const { return m_method.c_str(); }; + +private: + + int m_code; + std::string m_message; + std::string m_method; +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/IdVisitor.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/IdVisitor.h.svn-base new file mode 100644 index 000000000..81d745651 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/IdVisitor.h.svn-base @@ -0,0 +1,47 @@ +/****************************************************************************** + * $Id: idvisitor.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class IdVisitor : public SpatialIndex::IVisitor +{ +private: + std::vector<uint64_t> m_vector; + uint64_t nResults; + +public: + + IdVisitor(); + ~IdVisitor(); + + uint64_t GetResultCount() const { return nResults; } + std::vector<uint64_t>& GetResults() { return m_vector; } + + void visitNode(const SpatialIndex::INode& n); + void visitData(const SpatialIndex::IData& d); + void visitData(std::vector<const SpatialIndex::IData*>& v); +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Index.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Index.h.svn-base new file mode 100644 index 000000000..8f6ac52d3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Index.h.svn-base @@ -0,0 +1,68 @@ +/****************************************************************************** + * $Id: index.hpp 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class Index +{ + +public: + Index(const Tools::PropertySet& poProperties); + Index(const Tools::PropertySet& poProperties, int (*readNext)(SpatialIndex::id_type *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength)); + ~Index(); + + const Tools::PropertySet& GetProperties() { return m_properties; } + + bool insertFeature(uint64_t id, double *min, double *max); + + RTIndexType GetIndexType(); + void SetIndexType(RTIndexType v); + + RTStorageType GetIndexStorage(); + void SetIndexStorage(RTStorageType v); + + RTIndexVariant GetIndexVariant(); + void SetIndexVariant(RTStorageType v); + + SpatialIndex::ISpatialIndex& index() {return *m_rtree;} + SpatialIndex::StorageManager::IBuffer& buffer() {return *m_buffer;} + +private: + + void Initialize(); + SpatialIndex::IStorageManager* m_storage; + SpatialIndex::StorageManager::IBuffer* m_buffer; + SpatialIndex::ISpatialIndex* m_rtree; + + Tools::PropertySet m_properties; + + + void Setup(); + SpatialIndex::IStorageManager* CreateStorage(); + SpatialIndex::StorageManager::IBuffer* CreateIndexBuffer(SpatialIndex::IStorageManager& storage); + SpatialIndex::ISpatialIndex* CreateIndex(); +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/LeafQuery.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/LeafQuery.h.svn-base new file mode 100644 index 000000000..c1ba053e0 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/LeafQuery.h.svn-base @@ -0,0 +1,70 @@ +/****************************************************************************** + * $Id: boundsquery.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement a query of the index's leaves. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class LeafQueryResult; + +class LeafQuery : public SpatialIndex::IQueryStrategy +{ +private: + std::queue<SpatialIndex::id_type> m_ids; + std::vector<LeafQueryResult> m_results; +public: + + LeafQuery(); + ~LeafQuery() { } + void getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext); + std::vector<LeafQueryResult> const& GetResults() const {return m_results;} +}; + +class LeafQueryResult +{ +private: + std::vector<SpatialIndex::id_type> ids; + SpatialIndex::Region* bounds; + uint32_t m_id; + LeafQueryResult(); +public: + LeafQueryResult(uint32_t id) : bounds(0), m_id(id){}; + ~LeafQueryResult() {if (bounds!=0) delete bounds;}; + + /// Copy constructor. + LeafQueryResult(LeafQueryResult const& other); + + /// Assignment operator. + LeafQueryResult& operator=(LeafQueryResult const& rhs); + + std::vector<SpatialIndex::id_type> const& GetIDs() const; + void SetIDs(std::vector<SpatialIndex::id_type>& v); + const SpatialIndex::Region* GetBounds() const; + void SetBounds(const SpatialIndex::Region* b); + uint32_t getIdentifier() const {return m_id;} + void setIdentifier(uint32_t v) {m_id = v;} +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..3bdb8be2b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,17 @@ +spatialindexdir = $(includedir)/spatialindex/capi + +dist_spatialindex_HEADERS = \ + BoundsQuery.h \ + CountVisitor.h \ + CustomStorage.h \ + DataStream.h \ + Error.h \ + IdVisitor.h \ + Index.h \ + LeafQuery.h \ + ObjVisitor.h \ + sidx_api.h \ + sidx_config.h \ + sidx_impl.h \ + Utility.h + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/ObjVisitor.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/ObjVisitor.h.svn-base new file mode 100644 index 000000000..13438ba3d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/ObjVisitor.h.svn-base @@ -0,0 +1,48 @@ +/****************************************************************************** + * $Id: objvisitor.hpp 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the object visitor. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class ObjVisitor : public SpatialIndex::IVisitor +{ +private: + std::vector<SpatialIndex::IData*> m_vector; + uint64_t nResults; + +public: + + ObjVisitor(); + ~ObjVisitor(); + + uint32_t GetResultCount() const { return nResults; } + std::vector<SpatialIndex::IData*>& GetResults() { return m_vector; } + + void visitNode(const SpatialIndex::INode& n); + void visitData(const SpatialIndex::IData& d); + void visitData(std::vector<const SpatialIndex::IData*>& v); +}; + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Utility.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Utility.h.svn-base new file mode 100644 index 000000000..58dc1e9b6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/Utility.h.svn-base @@ -0,0 +1,30 @@ +/****************************************************************************** + * $Id: util.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement utilities. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +Tools::PropertySet* GetDefaults(); diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_api.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_api.h.svn-base new file mode 100644 index 000000000..a07131b77 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_api.h.svn-base @@ -0,0 +1,213 @@ +/****************************************************************************** + * $Id: sidx_api.h 1371 2009-08-05 04:39:21Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C API. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + + +#ifndef SIDX_API_H_INCLUDED +#define SIDX_API_H_INCLUDED + +#define SIDX_C_API 1 + +#include "sidx_config.h" + +IDX_C_START + +SIDX_DLL IndexH Index_Create(IndexPropertyH properties); + +SIDX_DLL IndexH Index_CreateWithStream( IndexPropertyH properties, + int (*readNext)(uint64_t *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, size_t *nDataLength) + ); + +SIDX_DLL void Index_Destroy(IndexH index); +SIDX_DLL IndexPropertyH Index_GetProperties(IndexH index); + +SIDX_DLL RTError Index_DeleteData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension); + +SIDX_DLL RTError Index_InsertData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension, + const uint8_t* pData, + size_t nDataLength); + +SIDX_DLL uint32_t Index_IsValid(IndexH index); + +SIDX_DLL RTError Index_Intersects_obj( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_Intersects_id( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_Intersects_count( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t* nResults); +SIDX_DLL RTError Index_NearestNeighbors_obj(IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_NearestNeighbors_id( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_GetBounds( IndexH index, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension); + + +SIDX_C_DLL RTError Index_GetLeaves( IndexH index, + uint32_t* nLeafNodes, + uint32_t** nLeafSizes, + int64_t** nLeafIDs, + int64_t*** nLeafChildIDs, + double*** pppdMin, + double*** pppdMax, + uint32_t* nDimension); + +SIDX_DLL void Index_DestroyObjResults(IndexItemH* results, uint32_t nResults); +SIDX_DLL void Index_ClearBuffer(IndexH index); +SIDX_DLL void Index_Free(void* object); + +SIDX_DLL void IndexItem_Destroy(IndexItemH item); +SIDX_DLL uint64_t IndexItem_GetID(IndexItemH item); + +SIDX_DLL RTError IndexItem_GetData(IndexItemH item, uint8_t** data, uint64_t* length); + +SIDX_DLL RTError IndexItem_GetBounds( IndexItemH item, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension); + +SIDX_DLL IndexPropertyH IndexProperty_Create(); +SIDX_DLL void IndexProperty_Destroy(IndexPropertyH hProp); + +SIDX_DLL RTError IndexProperty_SetIndexType(IndexPropertyH iprop, RTIndexType value); +SIDX_DLL RTIndexType IndexProperty_GetIndexType(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetDimension(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetDimension(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexVariant(IndexPropertyH iprop, RTIndexVariant value); +SIDX_DLL RTIndexVariant IndexProperty_GetIndexVariant(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexStorage(IndexPropertyH iprop, RTStorageType value); +SIDX_DLL RTStorageType IndexProperty_GetIndexStorage(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetPagesize(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetPagesize(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetIndexCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetLeafCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetLeafCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetLeafPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetLeafPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetIndexPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetRegionPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetRegionPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetPointPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetPointPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetBufferingCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetBufferingCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetEnsureTightMBRs(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetEnsureTightMBRs(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetOverwrite(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetOverwrite(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetNearMinimumOverlapFactor(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetNearMinimumOverlapFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetWriteThrough(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetWriteThrough(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFillFactor(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetFillFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetSplitDistributionFactor(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetSplitDistributionFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetTPRHorizon(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetTPRHorizon(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetReinsertFactor(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetReinsertFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFileName(IndexPropertyH iprop, const char* value); +SIDX_DLL char* IndexProperty_GetFileName(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFileNameExtensionDat(IndexPropertyH iprop, const char* value); +SIDX_DLL char* IndexProperty_GetFileNameExtensionDat(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFileNameExtensionIdx(IndexPropertyH iprop, const char* value); +SIDX_DLL char* IndexProperty_GetFileNameExtensionIdx(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetCustomStorageCallbacksSize(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetCustomStorageCallbacksSize(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetCustomStorageCallbacks(IndexPropertyH iprop, const void* value); +SIDX_DLL void* IndexProperty_GetCustomStorageCallbacks(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexID(IndexPropertyH iprop, int64_t value); +SIDX_DLL int64_t IndexProperty_GetIndexID(IndexPropertyH iprop); + +SIDX_C_DLL void* SIDX_NewBuffer(size_t bytes); +SIDX_C_DLL void SIDX_DeleteBuffer(void* buffer); + +SIDX_C_DLL char* SIDX_Version(); + +IDX_C_END + +#endif
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_config.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_config.h.svn-base new file mode 100644 index 000000000..439c701ce --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_config.h.svn-base @@ -0,0 +1,121 @@ +/****************************************************************************** + * $Id: sidx_config.h 1359 2009-07-31 04:44:50Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C API configuration + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef SIDX_CONFIG_H_INCLUDED +#define SIDX_CONFIG_H_INCLUDED + + +#ifdef _MSC_VER + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + + #include <windows.h> + #define STRDUP _strdup + #include "SpatialIndex.h" + #include <windows.h> + +#else + + #include <stdint.h> + #define SIDX_THREAD __thread + #include <SpatialIndex.h> + #define STRDUP strdup +#endif + +#include <sys/stat.h> + + + +class Item; +class Index; + +typedef enum +{ + RT_None = 0, + RT_Debug = 1, + RT_Warning = 2, + RT_Failure = 3, + RT_Fatal = 4 +} RTError; + +typedef enum +{ + RT_RTree = 0, + RT_MVRTree = 1, + RT_TPRTree = 2, + RT_InvalidIndexType = -99 +} RTIndexType; + +typedef enum +{ + RT_Memory = 0, + RT_Disk = 1, + RT_Custom = 2, + RT_InvalidStorageType = -99 +} RTStorageType; + +typedef enum +{ + RT_Linear = 0, + RT_Quadratic = 1, + RT_Star = 2, + RT_InvalidIndexVariant = -99 +} RTIndexVariant; + + +#ifdef __cplusplus +# define IDX_C_START extern "C" { +# define IDX_C_END } +#else +# define IDX_C_START +# define IDX_C_END +#endif + +typedef Index *IndexH; +typedef SpatialIndex::IData *IndexItemH; +typedef Tools::PropertySet *IndexPropertyH; + +#ifndef SIDX_C_DLL +#if defined(_MSC_VER) +# define SIDX_C_DLL __declspec(dllexport) +#else +# if defined(USE_GCC_VISIBILITY_FLAG) +# define SIDX_C_DLL __attribute__ ((visibility("default"))) +# else +# define SIDX_C_DLL +# endif +#endif +#endif + + +#endif diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_impl.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_impl.h.svn-base new file mode 100644 index 000000000..25416a924 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/.svn/text-base/sidx_impl.h.svn-base @@ -0,0 +1,46 @@ +/****************************************************************************** + * $Id: sidx_impl.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <stack> +#include <string> +#include <vector> +#include <stdexcept> +#include <sstream> +#include <cstring> + +#include <capi/sidx_config.h> + +#include <capi/Utility.h> +#include <capi/ObjVisitor.h> +#include <capi/IdVisitor.h> +#include <capi/CountVisitor.h> +#include <capi/BoundsQuery.h> +#include <capi/LeafQuery.h> +#include <capi/Error.h> +#include <capi/DataStream.h> +#include <capi/Index.h> +#include <capi/CustomStorage.h> diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/BoundsQuery.h b/sci-libs/libspatialindex/svn/trunk/include/capi/BoundsQuery.h new file mode 100644 index 000000000..42fa6582a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/BoundsQuery.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * $Id: boundsquery.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the bounds query. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class BoundsQuery : public SpatialIndex::IQueryStrategy +{ +private: + SpatialIndex::Region* m_bounds; + +public: + + BoundsQuery(); + ~BoundsQuery() { if (m_bounds !=0) delete m_bounds;} + void getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext); + + SpatialIndex::Region* GetBounds() const {return m_bounds; } +}; + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/CountVisitor.h b/sci-libs/libspatialindex/svn/trunk/include/capi/CountVisitor.h new file mode 100644 index 000000000..323f90aa9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/CountVisitor.h @@ -0,0 +1,45 @@ +/****************************************************************************** +* $Id$ +* +* Project: libsidx - A C API wrapper around libspatialindex +* Purpose: C++ objects to implement the count visitor. +* Author: Leonard Norrgård, leonard.norrgard@refactor.fi +* +****************************************************************************** +* Copyright (c) 2010, Leonard Norrgård +* +* All rights reserved. +* +* This library is free software; you can redistribute it and/or modify it under +* the terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; either version 2.1 of the License, or (at your option) +* any later version. + +* This library is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +* details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this library; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#pragma once + +class CountVisitor : public SpatialIndex::IVisitor +{ +private: + uint64_t nResults; + +public: + + CountVisitor(); + ~CountVisitor(); + + uint64_t GetResultCount() const { return nResults; } + + void visitNode(const SpatialIndex::INode& n); + void visitData(const SpatialIndex::IData& d); + void visitData(std::vector<const SpatialIndex::IData*>& v); +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/CustomStorage.h b/sci-libs/libspatialindex/svn/trunk/include/capi/CustomStorage.h new file mode 100644 index 000000000..35f208273 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/CustomStorage.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * $Id: CustomStorage.h 1385 2009-06-17 13:45:16Z nitro $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the custom storage manager. + * Author: Matthias (nitro) + * + ****************************************************************************** + * Copyright (c) 2010, Matthias (nitro) + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +namespace SpatialIndex +{ + namespace StorageManager + { + struct CustomStorageManagerCallbacks + { + CustomStorageManagerCallbacks() : context(0), createCallback(0), destroyCallback(0), loadByteArrayCallback(0), storeByteArrayCallback(0), deleteByteArrayCallback(0) + {} + + void* context; + void (*createCallback)( const void* context, int* errorCode ); + void (*destroyCallback)( const void* context, int* errorCode ); + void (*loadByteArrayCallback)( const void* context, const id_type page, uint32_t* len, byte** data, int* errorCode ); + void (*storeByteArrayCallback)( const void* context, id_type* page, const uint32_t len, const byte* const data, int* errorCode ); + void (*deleteByteArrayCallback)( const void* context, const id_type page, int* errorCode ); + }; + + class CustomStorageManager : public SpatialIndex::IStorageManager + { + public: + // I'd like this to be an enum, but casting between enums and ints is not nice + static const int NoError = 0; + static const int InvalidPageError = 1; + static const int IllegalStateError = 2; + + CustomStorageManager(Tools::PropertySet&); + + virtual ~CustomStorageManager(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + private: + CustomStorageManagerCallbacks callbacks; + + inline void processErrorCode(int errorCode, const id_type page); + }; // CustomStorageManager + + // factory function + IStorageManager* returnCustomStorageManager(Tools::PropertySet& in); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/DataStream.h b/sci-libs/libspatialindex/svn/trunk/include/capi/DataStream.h new file mode 100644 index 000000000..93a7f12a6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/DataStream.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * $Id: datastream.hpp 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the datastream. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class DataStream : public SpatialIndex::IDataStream +{ +public: + DataStream(int (*readNext)(SpatialIndex::id_type* id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength)); + ~DataStream(); + + SpatialIndex::IData* getNext(); + bool hasNext() throw (Tools::NotSupportedException); + + uint32_t size() throw (Tools::NotSupportedException); + void rewind() throw (Tools::NotSupportedException); + +protected: + SpatialIndex::RTree::Data* m_pNext; + SpatialIndex::id_type m_id; + +private: + int (*iterfunct)(SpatialIndex::id_type *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength); + + bool readData(); + bool m_bDoneReading; + +}; + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/Error.h b/sci-libs/libspatialindex/svn/trunk/include/capi/Error.h new file mode 100644 index 000000000..69d805d44 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/Error.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * $Id: error.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the error object. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class Error +{ +public: + + Error(int code, std::string const& message, std::string const& method); + + /// Copy constructor. + Error(Error const& other); + + /// Assignment operator. + Error& operator=(Error const& rhs); + + int GetCode() const { return m_code; }; + const char* GetMessage() const { return m_message.c_str(); }; + const char* GetMethod() const { return m_method.c_str(); }; + +private: + + int m_code; + std::string m_message; + std::string m_method; +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/IdVisitor.h b/sci-libs/libspatialindex/svn/trunk/include/capi/IdVisitor.h new file mode 100644 index 000000000..81d745651 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/IdVisitor.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * $Id: idvisitor.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class IdVisitor : public SpatialIndex::IVisitor +{ +private: + std::vector<uint64_t> m_vector; + uint64_t nResults; + +public: + + IdVisitor(); + ~IdVisitor(); + + uint64_t GetResultCount() const { return nResults; } + std::vector<uint64_t>& GetResults() { return m_vector; } + + void visitNode(const SpatialIndex::INode& n); + void visitData(const SpatialIndex::IData& d); + void visitData(std::vector<const SpatialIndex::IData*>& v); +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/Index.h b/sci-libs/libspatialindex/svn/trunk/include/capi/Index.h new file mode 100644 index 000000000..8f6ac52d3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/Index.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * $Id: index.hpp 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class Index +{ + +public: + Index(const Tools::PropertySet& poProperties); + Index(const Tools::PropertySet& poProperties, int (*readNext)(SpatialIndex::id_type *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength)); + ~Index(); + + const Tools::PropertySet& GetProperties() { return m_properties; } + + bool insertFeature(uint64_t id, double *min, double *max); + + RTIndexType GetIndexType(); + void SetIndexType(RTIndexType v); + + RTStorageType GetIndexStorage(); + void SetIndexStorage(RTStorageType v); + + RTIndexVariant GetIndexVariant(); + void SetIndexVariant(RTStorageType v); + + SpatialIndex::ISpatialIndex& index() {return *m_rtree;} + SpatialIndex::StorageManager::IBuffer& buffer() {return *m_buffer;} + +private: + + void Initialize(); + SpatialIndex::IStorageManager* m_storage; + SpatialIndex::StorageManager::IBuffer* m_buffer; + SpatialIndex::ISpatialIndex* m_rtree; + + Tools::PropertySet m_properties; + + + void Setup(); + SpatialIndex::IStorageManager* CreateStorage(); + SpatialIndex::StorageManager::IBuffer* CreateIndexBuffer(SpatialIndex::IStorageManager& storage); + SpatialIndex::ISpatialIndex* CreateIndex(); +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/LeafQuery.h b/sci-libs/libspatialindex/svn/trunk/include/capi/LeafQuery.h new file mode 100644 index 000000000..c1ba053e0 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/LeafQuery.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * $Id: boundsquery.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement a query of the index's leaves. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class LeafQueryResult; + +class LeafQuery : public SpatialIndex::IQueryStrategy +{ +private: + std::queue<SpatialIndex::id_type> m_ids; + std::vector<LeafQueryResult> m_results; +public: + + LeafQuery(); + ~LeafQuery() { } + void getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext); + std::vector<LeafQueryResult> const& GetResults() const {return m_results;} +}; + +class LeafQueryResult +{ +private: + std::vector<SpatialIndex::id_type> ids; + SpatialIndex::Region* bounds; + uint32_t m_id; + LeafQueryResult(); +public: + LeafQueryResult(uint32_t id) : bounds(0), m_id(id){}; + ~LeafQueryResult() {if (bounds!=0) delete bounds;}; + + /// Copy constructor. + LeafQueryResult(LeafQueryResult const& other); + + /// Assignment operator. + LeafQueryResult& operator=(LeafQueryResult const& rhs); + + std::vector<SpatialIndex::id_type> const& GetIDs() const; + void SetIDs(std::vector<SpatialIndex::id_type>& v); + const SpatialIndex::Region* GetBounds() const; + void SetBounds(const SpatialIndex::Region* b); + uint32_t getIdentifier() const {return m_id;} + void setIdentifier(uint32_t v) {m_id = v;} +}; diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/Makefile.am b/sci-libs/libspatialindex/svn/trunk/include/capi/Makefile.am new file mode 100644 index 000000000..3bdb8be2b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/Makefile.am @@ -0,0 +1,17 @@ +spatialindexdir = $(includedir)/spatialindex/capi + +dist_spatialindex_HEADERS = \ + BoundsQuery.h \ + CountVisitor.h \ + CustomStorage.h \ + DataStream.h \ + Error.h \ + IdVisitor.h \ + Index.h \ + LeafQuery.h \ + ObjVisitor.h \ + sidx_api.h \ + sidx_config.h \ + sidx_impl.h \ + Utility.h + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/ObjVisitor.h b/sci-libs/libspatialindex/svn/trunk/include/capi/ObjVisitor.h new file mode 100644 index 000000000..13438ba3d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/ObjVisitor.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * $Id: objvisitor.hpp 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the object visitor. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +class ObjVisitor : public SpatialIndex::IVisitor +{ +private: + std::vector<SpatialIndex::IData*> m_vector; + uint64_t nResults; + +public: + + ObjVisitor(); + ~ObjVisitor(); + + uint32_t GetResultCount() const { return nResults; } + std::vector<SpatialIndex::IData*>& GetResults() { return m_vector; } + + void visitNode(const SpatialIndex::INode& n); + void visitData(const SpatialIndex::IData& d); + void visitData(std::vector<const SpatialIndex::IData*>& v); +}; + diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/Utility.h b/sci-libs/libspatialindex/svn/trunk/include/capi/Utility.h new file mode 100644 index 000000000..58dc1e9b6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/Utility.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * $Id: util.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement utilities. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#pragma once + +Tools::PropertySet* GetDefaults(); diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_api.h b/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_api.h new file mode 100644 index 000000000..a07131b77 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_api.h @@ -0,0 +1,213 @@ +/****************************************************************************** + * $Id: sidx_api.h 1371 2009-08-05 04:39:21Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C API. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + + +#ifndef SIDX_API_H_INCLUDED +#define SIDX_API_H_INCLUDED + +#define SIDX_C_API 1 + +#include "sidx_config.h" + +IDX_C_START + +SIDX_DLL IndexH Index_Create(IndexPropertyH properties); + +SIDX_DLL IndexH Index_CreateWithStream( IndexPropertyH properties, + int (*readNext)(uint64_t *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, size_t *nDataLength) + ); + +SIDX_DLL void Index_Destroy(IndexH index); +SIDX_DLL IndexPropertyH Index_GetProperties(IndexH index); + +SIDX_DLL RTError Index_DeleteData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension); + +SIDX_DLL RTError Index_InsertData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension, + const uint8_t* pData, + size_t nDataLength); + +SIDX_DLL uint32_t Index_IsValid(IndexH index); + +SIDX_DLL RTError Index_Intersects_obj( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_Intersects_id( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_Intersects_count( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t* nResults); +SIDX_DLL RTError Index_NearestNeighbors_obj(IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_NearestNeighbors_id( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** items, + uint64_t* nResults); + +SIDX_DLL RTError Index_GetBounds( IndexH index, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension); + + +SIDX_C_DLL RTError Index_GetLeaves( IndexH index, + uint32_t* nLeafNodes, + uint32_t** nLeafSizes, + int64_t** nLeafIDs, + int64_t*** nLeafChildIDs, + double*** pppdMin, + double*** pppdMax, + uint32_t* nDimension); + +SIDX_DLL void Index_DestroyObjResults(IndexItemH* results, uint32_t nResults); +SIDX_DLL void Index_ClearBuffer(IndexH index); +SIDX_DLL void Index_Free(void* object); + +SIDX_DLL void IndexItem_Destroy(IndexItemH item); +SIDX_DLL uint64_t IndexItem_GetID(IndexItemH item); + +SIDX_DLL RTError IndexItem_GetData(IndexItemH item, uint8_t** data, uint64_t* length); + +SIDX_DLL RTError IndexItem_GetBounds( IndexItemH item, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension); + +SIDX_DLL IndexPropertyH IndexProperty_Create(); +SIDX_DLL void IndexProperty_Destroy(IndexPropertyH hProp); + +SIDX_DLL RTError IndexProperty_SetIndexType(IndexPropertyH iprop, RTIndexType value); +SIDX_DLL RTIndexType IndexProperty_GetIndexType(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetDimension(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetDimension(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexVariant(IndexPropertyH iprop, RTIndexVariant value); +SIDX_DLL RTIndexVariant IndexProperty_GetIndexVariant(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexStorage(IndexPropertyH iprop, RTStorageType value); +SIDX_DLL RTStorageType IndexProperty_GetIndexStorage(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetPagesize(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetPagesize(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetIndexCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetLeafCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetLeafCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetLeafPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetLeafPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetIndexPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetRegionPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetRegionPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetPointPoolCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetPointPoolCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetBufferingCapacity(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetBufferingCapacity(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetEnsureTightMBRs(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetEnsureTightMBRs(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetOverwrite(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetOverwrite(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetNearMinimumOverlapFactor(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetNearMinimumOverlapFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetWriteThrough(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetWriteThrough(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFillFactor(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetFillFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetSplitDistributionFactor(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetSplitDistributionFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetTPRHorizon(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetTPRHorizon(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetReinsertFactor(IndexPropertyH iprop, double value); +SIDX_DLL double IndexProperty_GetReinsertFactor(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFileName(IndexPropertyH iprop, const char* value); +SIDX_DLL char* IndexProperty_GetFileName(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFileNameExtensionDat(IndexPropertyH iprop, const char* value); +SIDX_DLL char* IndexProperty_GetFileNameExtensionDat(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetFileNameExtensionIdx(IndexPropertyH iprop, const char* value); +SIDX_DLL char* IndexProperty_GetFileNameExtensionIdx(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetCustomStorageCallbacksSize(IndexPropertyH iprop, uint32_t value); +SIDX_DLL uint32_t IndexProperty_GetCustomStorageCallbacksSize(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetCustomStorageCallbacks(IndexPropertyH iprop, const void* value); +SIDX_DLL void* IndexProperty_GetCustomStorageCallbacks(IndexPropertyH iprop); + +SIDX_DLL RTError IndexProperty_SetIndexID(IndexPropertyH iprop, int64_t value); +SIDX_DLL int64_t IndexProperty_GetIndexID(IndexPropertyH iprop); + +SIDX_C_DLL void* SIDX_NewBuffer(size_t bytes); +SIDX_C_DLL void SIDX_DeleteBuffer(void* buffer); + +SIDX_C_DLL char* SIDX_Version(); + +IDX_C_END + +#endif
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_config.h b/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_config.h new file mode 100644 index 000000000..439c701ce --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_config.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * $Id: sidx_config.h 1359 2009-07-31 04:44:50Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C API configuration + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef SIDX_CONFIG_H_INCLUDED +#define SIDX_CONFIG_H_INCLUDED + + +#ifdef _MSC_VER + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + + #include <windows.h> + #define STRDUP _strdup + #include "SpatialIndex.h" + #include <windows.h> + +#else + + #include <stdint.h> + #define SIDX_THREAD __thread + #include <SpatialIndex.h> + #define STRDUP strdup +#endif + +#include <sys/stat.h> + + + +class Item; +class Index; + +typedef enum +{ + RT_None = 0, + RT_Debug = 1, + RT_Warning = 2, + RT_Failure = 3, + RT_Fatal = 4 +} RTError; + +typedef enum +{ + RT_RTree = 0, + RT_MVRTree = 1, + RT_TPRTree = 2, + RT_InvalidIndexType = -99 +} RTIndexType; + +typedef enum +{ + RT_Memory = 0, + RT_Disk = 1, + RT_Custom = 2, + RT_InvalidStorageType = -99 +} RTStorageType; + +typedef enum +{ + RT_Linear = 0, + RT_Quadratic = 1, + RT_Star = 2, + RT_InvalidIndexVariant = -99 +} RTIndexVariant; + + +#ifdef __cplusplus +# define IDX_C_START extern "C" { +# define IDX_C_END } +#else +# define IDX_C_START +# define IDX_C_END +#endif + +typedef Index *IndexH; +typedef SpatialIndex::IData *IndexItemH; +typedef Tools::PropertySet *IndexPropertyH; + +#ifndef SIDX_C_DLL +#if defined(_MSC_VER) +# define SIDX_C_DLL __declspec(dllexport) +#else +# if defined(USE_GCC_VISIBILITY_FLAG) +# define SIDX_C_DLL __attribute__ ((visibility("default"))) +# else +# define SIDX_C_DLL +# endif +#endif +#endif + + +#endif diff --git a/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_impl.h b/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_impl.h new file mode 100644 index 000000000..25416a924 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/capi/sidx_impl.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * $Id: sidx_impl.hpp 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <stack> +#include <string> +#include <vector> +#include <stdexcept> +#include <sstream> +#include <cstring> + +#include <capi/sidx_config.h> + +#include <capi/Utility.h> +#include <capi/ObjVisitor.h> +#include <capi/IdVisitor.h> +#include <capi/CountVisitor.h> +#include <capi/BoundsQuery.h> +#include <capi/LeafQuery.h> +#include <capi/Error.h> +#include <capi/DataStream.h> +#include <capi/Index.h> +#include <capi/CustomStorage.h> diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/all-wcprops new file mode 100644 index 000000000..3aa082be9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/all-wcprops @@ -0,0 +1,41 @@ +K 25 +svn:wc:ra_dav:version-url +V 59 +/spatialindex/!svn/ver/192/spatialindex/trunk/include/tools +END +PointerPool.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/spatialindex/!svn/ver/130/spatialindex/trunk/include/tools/PointerPool.h +END +PoolPointer.h +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/99/spatialindex/trunk/include/tools/PoolPointer.h +END +Tools.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/192/spatialindex/trunk/include/tools/Tools.h +END +rand48.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/99/spatialindex/trunk/include/tools/rand48.h +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/138/spatialindex/trunk/include/tools/Makefile.am +END +SmartPointer.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/spatialindex/!svn/ver/99/spatialindex/trunk/include/tools/SmartPointer.h +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/dir-prop-base new file mode 100644 index 000000000..a57f5442b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 21 +Makefile +Makefile.in + +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/entries b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/entries new file mode 100644 index 000000000..e863e3800 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/entries @@ -0,0 +1,232 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/include/tools +http://svn.gispython.org/spatialindex + + + +2010-10-14T13:18:23.380119Z +192 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +PointerPool.h +file + + + + +2011-08-01T00:42:34.214469Z +6cd7bba0452721df79787831b0e380e9 +2009-08-13T15:24:35.589450Z +130 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +2232 + +PoolPointer.h +file + + + + +2011-08-01T00:42:34.214469Z +0b9575f543d7a54dd89aa3ec884b6e44 +2009-07-18T22:19:07.374702Z +99 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +2412 + +Tools.h +file + + + + +2011-08-01T00:42:34.214469Z +f383cf79a414e56857149c09eaf8f5d0 +2010-10-14T13:18:23.380119Z +192 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +13393 + +rand48.h +file + + + + +2011-08-01T00:42:34.214469Z +931a08a36d9cc3cd6d7f2295d1c90d7b +2009-07-18T22:19:07.374702Z +99 +mhadji + + + + + + + + + + + + + + + + + + + + + +367 + +Makefile.am +file + + + + +2011-08-01T00:42:34.214469Z +86eb1cf3433f87d161f17cc083feaab8 +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +163 + +SmartPointer.h +file + + + + +2011-08-01T00:42:34.217427Z +db9e23168b4d63476a2d06ad39b492df +2009-07-18T22:19:07.374702Z +99 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +2012 + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/PointerPool.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/PointerPool.h.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/PointerPool.h.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/PoolPointer.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/PoolPointer.h.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/PoolPointer.h.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/SmartPointer.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/SmartPointer.h.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/SmartPointer.h.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/Tools.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/Tools.h.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/prop-base/Tools.h.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..ebad2dde3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,7 @@ +spatialindexdir = $(includedir)/spatialindex/tools + +dist_spatialindex_HEADERS = Tools.h \ + PointerPool.h \ + PoolPointer.h \ + SmartPointer.h \ + rand48.h
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/PointerPool.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/PointerPool.h.svn-base new file mode 100644 index 000000000..7431ffc13 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/PointerPool.h.svn-base @@ -0,0 +1,117 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "PoolPointer.h" + +namespace Tools +{ + template <class X> class PointerPool + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + X* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<X> acquire() + { + X* p = 0; + + if (! m_pool.empty()) + { + p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + m_hits++; + #endif + } + else + { + p = new X(); + #ifndef NDEBUG + m_pointerCount++; + m_misses++; + #endif + } + + return PoolPointer<X>(p, this); + } + + void release(X* p) + { + if (m_pool.size() < m_capacity) + { + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + private: + uint32_t m_capacity; + std::stack<X*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/PoolPointer.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/PoolPointer.h.svn-base new file mode 100644 index 000000000..3382e8487 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/PoolPointer.h.svn-base @@ -0,0 +1,96 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "PointerPool.h" + +namespace Tools +{ + template <class X> class PointerPool; + + template <class X> class PoolPointer + { + public: + explicit PoolPointer(X* p = 0) : m_pointer(p), m_pPool(0) { m_prev = m_next = this; } + explicit PoolPointer(X* p, PointerPool<X>* pPool) throw() : m_pointer(p), m_pPool(pPool) { m_prev = m_next = this; } + ~PoolPointer() { release(); } + PoolPointer(const PoolPointer& p) throw() { acquire(p); } + PoolPointer& operator=(const PoolPointer& p) + { + if (this != &p) + { + release(); + acquire(p); + } + return *this; + } + + X& operator*() const throw() { return *m_pointer; } + X* operator->() const throw() { return m_pointer; } + X* get() const throw() { return m_pointer; } + bool unique() const throw() { return m_prev ? m_prev == this : true; } + void relinquish() throw() + { + m_pPool = 0; + m_pointer = 0; + release(); + } + + private: + X* m_pointer; + mutable const PoolPointer* m_prev; + mutable const PoolPointer* m_next; + PointerPool<X>* m_pPool; + + void acquire(const PoolPointer& p) throw() + { + m_pPool = p.m_pPool; + m_pointer = p.m_pointer; + m_next = p.m_next; + m_next->m_prev = this; + m_prev = &p; + #ifndef mutable + p.m_next = this; + #else + (const_cast<linked_ptr<X>*>(&p))->m_next = this; + #endif + } + + void release() + { + if (unique()) + { + if (m_pPool != 0) m_pPool->release(m_pointer); + else delete m_pointer; + } + else + { + m_prev->m_next = m_next; + m_next->m_prev = m_prev; + m_prev = m_next = 0; + } + m_pointer = 0; + m_pPool = 0; + } + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/SmartPointer.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/SmartPointer.h.svn-base new file mode 100644 index 000000000..d9ef7a57b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/SmartPointer.h.svn-base @@ -0,0 +1,78 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace Tools +{ + template <class X> class SmartPointer + { + public: + explicit SmartPointer(X* p = 0) throw() : m_pointer(p) { m_prev = m_next = this; } + ~SmartPointer() { release(); } + SmartPointer(const SmartPointer& p) throw() { acquire(p); } + SmartPointer& operator=(const SmartPointer& p) + { + if (this != &p) + { + release(); + acquire(p); + } + return *this; + } + + X& operator*() const throw() { return *m_pointer; } + X* operator->() const throw() { return m_pointer; } + X* get() const throw() { return m_pointer; } + bool unique() const throw() { return m_prev ? m_prev == this : true; } + + private: + X* m_pointer; + mutable const SmartPointer* m_prev; + mutable const SmartPointer* m_next; + + void acquire(const SmartPointer& p) throw() + { + m_pointer = p.m_pointer; + m_next = p.m_next; + m_next->m_prev = this; + m_prev = &p; + #ifndef mutable + p.m_next = this; + #else + (const_cast<linked_ptr<X>*>(&p))->m_next = this; + #endif + } + + void release() + { + if (unique()) delete m_pointer; + else + { + m_prev->m_next = m_next; + m_next->m_prev = m_prev; + m_prev = m_next = 0; + } + m_pointer = 0; + } + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/Tools.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/Tools.h.svn-base new file mode 100644 index 000000000..f41ed9d65 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/Tools.h.svn-base @@ -0,0 +1,513 @@ +// Spatial Index Library
+//
+// Copyright (C) 2004 Navel Ltd.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Email:
+// mhadji@gmail.com
+
+#pragma once
+
+#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64
+ typedef __int8 int8_t;
+ typedef __int16 int16_t;
+ typedef __int32 int32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+
+// Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
+#pragma warning( disable: 4251 )
+
+#else
+ #include <stdint.h>
+#endif
+
+#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64
+ #ifdef SPATIALINDEX_CREATE_DLL
+ #define SIDX_DLL __declspec(dllexport)
+ #else
+ #define SIDX_DLL __declspec(dllimport)
+ #endif
+#else
+ #define SIDX_DLL
+#endif
+
+#include <assert.h>
+#include <iostream>
+#include <iomanip>
+#include <iterator>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <queue>
+#include <vector>
+#include <map>
+#include <set>
+#include <stack>
+#include <list>
+#include <algorithm>
+// #include <cmath>
+// #include <limits>
+// #include <climits>
+
+#if HAVE_PTHREAD_H
+ #include <pthread.h>
+#endif
+
+#include "SmartPointer.h"
+#include "PointerPool.h"
+#include "PoolPointer.h"
+
+typedef uint8_t byte;
+
+namespace Tools
+{
+ SIDX_DLL enum IntervalType
+ {
+ IT_RIGHTOPEN = 0x0,
+ IT_LEFTOPEN,
+ IT_OPEN,
+ IT_CLOSED
+ };
+
+ SIDX_DLL enum VariantType
+ {
+ VT_LONG = 0x0,
+ VT_BYTE,
+ VT_SHORT,
+ VT_FLOAT,
+ VT_DOUBLE,
+ VT_CHAR,
+ VT_USHORT,
+ VT_ULONG,
+ VT_INT,
+ VT_UINT,
+ VT_BOOL,
+ VT_PCHAR,
+ VT_PVOID,
+ VT_EMPTY,
+ VT_LONGLONG,
+ VT_ULONGLONG
+ };
+
+ SIDX_DLL enum FileMode
+ {
+ APPEND = 0x0,
+ CREATE
+ };
+
+ //
+ // Exceptions
+ //
+ class SIDX_DLL Exception
+ {
+ public:
+ virtual std::string what() = 0;
+ virtual ~Exception() {}
+ };
+
+ class SIDX_DLL IndexOutOfBoundsException : public Exception
+ {
+ public:
+ IndexOutOfBoundsException(size_t i);
+ virtual ~IndexOutOfBoundsException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // IndexOutOfBoundsException
+
+ class SIDX_DLL IllegalArgumentException : public Exception
+ {
+ public:
+ IllegalArgumentException(std::string s);
+ virtual ~IllegalArgumentException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // IllegalArgumentException
+
+ class SIDX_DLL IllegalStateException : public Exception
+ {
+ public:
+ IllegalStateException(std::string s);
+ virtual ~IllegalStateException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // IllegalStateException
+
+ class SIDX_DLL EndOfStreamException : public Exception
+ {
+ public:
+ EndOfStreamException(std::string s);
+ virtual ~EndOfStreamException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // EndOfStreamException
+
+ class SIDX_DLL ResourceLockedException : public Exception
+ {
+ public:
+ ResourceLockedException(std::string s);
+ virtual ~ResourceLockedException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // ResourceLockedException
+
+ class SIDX_DLL NotSupportedException : public Exception
+ {
+ public:
+ NotSupportedException(std::string s);
+ virtual ~NotSupportedException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // NotSupportedException
+
+ //
+ // Interfaces
+ //
+ class SIDX_DLL IInterval
+ {
+ public:
+ virtual ~IInterval() {}
+
+ virtual double getLowerBound() const = 0;
+ virtual double getUpperBound() const = 0;
+ virtual void setBounds(double, double) = 0;
+ virtual bool intersectsInterval(const IInterval&) const = 0;
+ virtual bool intersectsInterval(IntervalType type, const double start, const double end) const = 0;
+ virtual bool containsInterval(const IInterval&) const = 0;
+ virtual IntervalType getIntervalType() const = 0;
+ }; // IInterval
+
+ class SIDX_DLL IObject
+ {
+ public:
+ virtual ~IObject() {}
+
+ virtual IObject* clone() = 0;
+ // return a new object that is an exact copy of this one.
+ // IMPORTANT: do not return the this pointer!
+ }; // IObject
+
+ class SIDX_DLL ISerializable
+ {
+ public:
+ virtual ~ISerializable() {}
+
+ virtual uint32_t getByteArraySize() = 0;
+ // returns the size of the required byte array.
+ virtual void loadFromByteArray(const byte* data) = 0;
+ // load this object using the byte array.
+ virtual void storeToByteArray(byte** data, uint32_t& length) = 0;
+ // store this object in the byte array.
+ };
+
+ class SIDX_DLL IComparable
+ {
+ public:
+ virtual ~IComparable() {}
+
+ virtual bool operator<(const IComparable& o) const = 0;
+ virtual bool operator>(const IComparable& o) const = 0;
+ virtual bool operator==(const IComparable& o) const = 0;
+ }; //IComparable
+
+ class SIDX_DLL IObjectComparator
+ {
+ public:
+ virtual ~IObjectComparator() {}
+
+ virtual int compare(IObject* o1, IObject* o2) = 0;
+ }; // IObjectComparator
+
+ class SIDX_DLL IObjectStream
+ {
+ public:
+ virtual ~IObjectStream() {}
+
+ virtual IObject* getNext() = 0;
+ // returns a pointer to the next entry in the
+ // stream or 0 at the end of the stream.
+
+ virtual bool hasNext() = 0;
+ // returns true if there are more items in the stream.
+
+ virtual uint32_t size() = 0;
+ // returns the total number of entries available in the stream.
+
+ virtual void rewind() = 0;
+ // sets the stream pointer to the first entry, if possible.
+ }; // IObjectStream
+
+ //
+ // Classes & Functions
+ //
+
+ class SIDX_DLL Variant
+ {
+ public:
+ Variant();
+
+ VariantType m_varType;
+
+ union
+ {
+ int16_t iVal; // VT_SHORT
+ int32_t lVal; // VT_LONG
+ int64_t llVal; // VT_LONGLONG
+ byte bVal; // VT_BYTE
+ float fltVal; // VT_FLOAT
+ double dblVal; // VT_DOUBLE
+ char cVal; // VT_CHAR
+ uint16_t uiVal; // VT_USHORT
+ uint32_t ulVal; // VT_ULONG
+ uint64_t ullVal; // VT_ULONGLONG
+ bool blVal; // VT_BOOL
+ char* pcVal; // VT_PCHAR
+ void* pvVal; // VT_PVOID
+ } m_val;
+ }; // Variant
+
+ class SIDX_DLL PropertySet;
+ SIDX_DLL std::ostream& operator<<(std::ostream& os, const Tools::PropertySet& p);
+
+ class SIDX_DLL PropertySet : public ISerializable
+ {
+ public:
+ PropertySet();
+ PropertySet(const byte* data);
+ virtual ~PropertySet();
+
+ Variant getProperty(std::string property);
+ void setProperty(std::string property, Variant& v);
+ void removeProperty(std::string property);
+
+ virtual uint32_t getByteArraySize();
+ virtual void loadFromByteArray(const byte* data);
+ virtual void storeToByteArray(byte** data, uint32_t& length);
+
+ private:
+ std::map<std::string, Variant> m_propertySet;
+#ifdef HAVE_PTHREAD_H
+ pthread_rwlock_t m_rwLock;
+#else
+ bool m_rwLock;
+#endif
+ friend SIDX_DLL std::ostream& Tools::operator<<(std::ostream& os, const Tools::PropertySet& p);
+ }; // PropertySet
+
+ // does not support degenerate intervals.
+ class SIDX_DLL Interval : public IInterval
+ {
+ public:
+ Interval();
+ Interval(IntervalType, double, double);
+ Interval(double, double);
+ Interval(const Interval&);
+ virtual ~Interval() {}
+ virtual IInterval& operator=(const IInterval&);
+
+ virtual bool operator==(const Interval&) const;
+ virtual bool operator!=(const Interval&) const;
+ virtual double getLowerBound() const;
+ virtual double getUpperBound() const;
+ virtual void setBounds(double, double);
+ virtual bool intersectsInterval(const IInterval&) const;
+ virtual bool intersectsInterval(IntervalType type, const double start, const double end) const;
+ virtual bool containsInterval(const IInterval&) const;
+ virtual IntervalType getIntervalType() const;
+
+ IntervalType m_type;
+ double m_low;
+ double m_high;
+ }; // Interval
+
+ SIDX_DLL std::ostream& operator<<(std::ostream& os, const Tools::Interval& iv);
+
+ class SIDX_DLL Random
+ {
+ public:
+ Random();
+ Random(uint32_t seed, uint16_t xsubi0);
+ virtual ~Random();
+
+ int32_t nextUniformLong();
+ // returns a uniformly distributed long.
+ uint32_t nextUniformUnsignedLong();
+ // returns a uniformly distributed unsigned long.
+ int32_t nextUniformLong(int32_t low, int32_t high);
+ // returns a uniformly distributed long in the range [low, high).
+ uint32_t nextUniformUnsignedLong(uint32_t low, uint32_t high);
+ // returns a uniformly distributed unsigned long in the range [low, high).
+ int64_t nextUniformLongLong();
+ // returns a uniformly distributed long long.
+ uint64_t nextUniformUnsignedLongLong();
+ // returns a uniformly distributed unsigned long long.
+ int64_t nextUniformLongLong(int64_t low, int64_t high);
+ // returns a uniformly distributed unsigned long long in the range [low, high).
+ uint64_t nextUniformUnsignedLongLong(uint64_t low, uint64_t high);
+ // returns a uniformly distributed unsigned long long in the range [low, high).
+ int16_t nextUniformShort();
+ // returns a uniformly distributed short.
+ uint16_t nextUniformUnsignedShort();
+ // returns a uniformly distributed unsigned short.
+ double nextUniformDouble();
+ // returns a uniformly distributed double in the range [0, 1).
+ double nextUniformDouble(double low, double high);
+ // returns a uniformly distributed double in the range [low, high).
+
+ bool flipCoin();
+
+ private:
+ void initDrand(uint32_t seed, uint16_t xsubi0);
+
+ uint16_t* m_pBuffer;
+ }; // Random
+
+ class SIDX_DLL SharedLock
+ {
+ public:
+ #if HAVE_PTHREAD_H
+ SharedLock(pthread_rwlock_t* pLock);
+ ~SharedLock();
+
+ private:
+ pthread_rwlock_t* m_pLock;
+ #endif
+ }; // SharedLock
+
+ class SIDX_DLL ExclusiveLock
+ {
+ public:
+ #if HAVE_PTHREAD_H
+ ExclusiveLock(pthread_rwlock_t* pLock);
+ ~ExclusiveLock();
+
+ private:
+ pthread_rwlock_t* m_pLock;
+ #endif
+ }; // ExclusiveLock
+
+ class SIDX_DLL BufferedFile
+ {
+ public:
+ BufferedFile(uint32_t u32BufferSize = 16384);
+ virtual ~BufferedFile();
+
+ virtual void close();
+ virtual bool eof();
+ virtual void rewind() = 0;
+ virtual void seek(std::fstream::off_type offset) = 0;
+
+ protected:
+ std::fstream m_file;
+ char* m_buffer;
+ uint32_t m_u32BufferSize;
+ bool m_bEOF;
+ };
+
+ class SIDX_DLL BufferedFileReader : public BufferedFile
+ {
+ public:
+ BufferedFileReader();
+ BufferedFileReader(const std::string& sFileName, uint32_t u32BufferSize = 32768);
+ virtual ~BufferedFileReader();
+
+ virtual void open(const std::string& sFileName);
+ virtual void rewind();
+ virtual void seek(std::fstream::off_type offset);
+
+ virtual uint8_t readUInt8();
+ virtual uint16_t readUInt16();
+ virtual uint32_t readUInt32();
+ virtual uint64_t readUInt64();
+ virtual float readFloat();
+ virtual double readDouble();
+ virtual bool readBoolean();
+ virtual std::string readString();
+ virtual void readBytes(uint32_t u32Len, byte** pData);
+ };
+
+ class SIDX_DLL BufferedFileWriter : public BufferedFile
+ {
+ public:
+ BufferedFileWriter();
+ BufferedFileWriter(const std::string& sFileName, FileMode mode = CREATE, uint32_t u32BufferSize = 32768);
+ virtual ~BufferedFileWriter();
+
+ virtual void open(const std::string& sFileName, FileMode mode = CREATE);
+ virtual void rewind();
+ virtual void seek(std::fstream::off_type offset);
+
+ virtual void write(uint8_t i);
+ virtual void write(uint16_t i);
+ virtual void write(uint32_t i);
+ virtual void write(uint64_t i);
+ virtual void write(float i);
+ virtual void write(double i);
+ virtual void write(bool b);
+ virtual void write(const std::string& s);
+ virtual void write(uint32_t u32Len, byte* pData);
+ };
+
+ class SIDX_DLL TemporaryFile
+ {
+ public:
+ TemporaryFile();
+ virtual ~TemporaryFile();
+
+ void rewindForReading();
+ void rewindForWriting();
+ bool eof();
+ std::string getFileName() const;
+
+ uint8_t readUInt8();
+ uint16_t readUInt16();
+ uint32_t readUInt32();
+ uint64_t readUInt64();
+ float readFloat();
+ double readDouble();
+ std::string readString();
+ void readBytes(uint32_t u32Len, byte** pData);
+
+ void write(uint8_t i);
+ void write(uint16_t i);
+ void write(uint32_t i);
+ void write(uint64_t i);
+ void write(float i);
+ void write(double i);
+ void write(const std::string& s);
+ void write(uint32_t u32Len, byte* pData);
+
+ private:
+ std::string m_sFile;
+ BufferedFile* m_pFile;
+ };
+}
+
diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/rand48.h.svn-base b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/rand48.h.svn-base new file mode 100644 index 000000000..fd2063ef7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/.svn/text-base/rand48.h.svn-base @@ -0,0 +1,11 @@ +#pragma once + +extern void srand48(long seed); +extern unsigned short *seed48(unsigned short xseed[3]); +extern long nrand48(unsigned short xseed[3]); +extern long mrand48(void); +extern long lrand48(void); +extern void lcong48(unsigned short p[7]); +extern long jrand48(unsigned short xseed[3]); +extern double erand48(unsigned short xseed[3]); +extern double drand48(void); diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/Makefile.am b/sci-libs/libspatialindex/svn/trunk/include/tools/Makefile.am new file mode 100644 index 000000000..ebad2dde3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/Makefile.am @@ -0,0 +1,7 @@ +spatialindexdir = $(includedir)/spatialindex/tools + +dist_spatialindex_HEADERS = Tools.h \ + PointerPool.h \ + PoolPointer.h \ + SmartPointer.h \ + rand48.h
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/PointerPool.h b/sci-libs/libspatialindex/svn/trunk/include/tools/PointerPool.h new file mode 100755 index 000000000..7431ffc13 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/PointerPool.h @@ -0,0 +1,117 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "PoolPointer.h" + +namespace Tools +{ + template <class X> class PointerPool + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + X* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<X> acquire() + { + X* p = 0; + + if (! m_pool.empty()) + { + p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + m_hits++; + #endif + } + else + { + p = new X(); + #ifndef NDEBUG + m_pointerCount++; + m_misses++; + #endif + } + + return PoolPointer<X>(p, this); + } + + void release(X* p) + { + if (m_pool.size() < m_capacity) + { + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + private: + uint32_t m_capacity; + std::stack<X*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/PoolPointer.h b/sci-libs/libspatialindex/svn/trunk/include/tools/PoolPointer.h new file mode 100755 index 000000000..3382e8487 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/PoolPointer.h @@ -0,0 +1,96 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "PointerPool.h" + +namespace Tools +{ + template <class X> class PointerPool; + + template <class X> class PoolPointer + { + public: + explicit PoolPointer(X* p = 0) : m_pointer(p), m_pPool(0) { m_prev = m_next = this; } + explicit PoolPointer(X* p, PointerPool<X>* pPool) throw() : m_pointer(p), m_pPool(pPool) { m_prev = m_next = this; } + ~PoolPointer() { release(); } + PoolPointer(const PoolPointer& p) throw() { acquire(p); } + PoolPointer& operator=(const PoolPointer& p) + { + if (this != &p) + { + release(); + acquire(p); + } + return *this; + } + + X& operator*() const throw() { return *m_pointer; } + X* operator->() const throw() { return m_pointer; } + X* get() const throw() { return m_pointer; } + bool unique() const throw() { return m_prev ? m_prev == this : true; } + void relinquish() throw() + { + m_pPool = 0; + m_pointer = 0; + release(); + } + + private: + X* m_pointer; + mutable const PoolPointer* m_prev; + mutable const PoolPointer* m_next; + PointerPool<X>* m_pPool; + + void acquire(const PoolPointer& p) throw() + { + m_pPool = p.m_pPool; + m_pointer = p.m_pointer; + m_next = p.m_next; + m_next->m_prev = this; + m_prev = &p; + #ifndef mutable + p.m_next = this; + #else + (const_cast<linked_ptr<X>*>(&p))->m_next = this; + #endif + } + + void release() + { + if (unique()) + { + if (m_pPool != 0) m_pPool->release(m_pointer); + else delete m_pointer; + } + else + { + m_prev->m_next = m_next; + m_next->m_prev = m_prev; + m_prev = m_next = 0; + } + m_pointer = 0; + m_pPool = 0; + } + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/SmartPointer.h b/sci-libs/libspatialindex/svn/trunk/include/tools/SmartPointer.h new file mode 100755 index 000000000..d9ef7a57b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/SmartPointer.h @@ -0,0 +1,78 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace Tools +{ + template <class X> class SmartPointer + { + public: + explicit SmartPointer(X* p = 0) throw() : m_pointer(p) { m_prev = m_next = this; } + ~SmartPointer() { release(); } + SmartPointer(const SmartPointer& p) throw() { acquire(p); } + SmartPointer& operator=(const SmartPointer& p) + { + if (this != &p) + { + release(); + acquire(p); + } + return *this; + } + + X& operator*() const throw() { return *m_pointer; } + X* operator->() const throw() { return m_pointer; } + X* get() const throw() { return m_pointer; } + bool unique() const throw() { return m_prev ? m_prev == this : true; } + + private: + X* m_pointer; + mutable const SmartPointer* m_prev; + mutable const SmartPointer* m_next; + + void acquire(const SmartPointer& p) throw() + { + m_pointer = p.m_pointer; + m_next = p.m_next; + m_next->m_prev = this; + m_prev = &p; + #ifndef mutable + p.m_next = this; + #else + (const_cast<linked_ptr<X>*>(&p))->m_next = this; + #endif + } + + void release() + { + if (unique()) delete m_pointer; + else + { + m_prev->m_next = m_next; + m_next->m_prev = m_prev; + m_prev = m_next = 0; + } + m_pointer = 0; + } + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/Tools.h b/sci-libs/libspatialindex/svn/trunk/include/tools/Tools.h new file mode 100755 index 000000000..f41ed9d65 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/Tools.h @@ -0,0 +1,513 @@ +// Spatial Index Library
+//
+// Copyright (C) 2004 Navel Ltd.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Email:
+// mhadji@gmail.com
+
+#pragma once
+
+#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64
+ typedef __int8 int8_t;
+ typedef __int16 int16_t;
+ typedef __int32 int32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+
+// Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
+#pragma warning( disable: 4251 )
+
+#else
+ #include <stdint.h>
+#endif
+
+#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64
+ #ifdef SPATIALINDEX_CREATE_DLL
+ #define SIDX_DLL __declspec(dllexport)
+ #else
+ #define SIDX_DLL __declspec(dllimport)
+ #endif
+#else
+ #define SIDX_DLL
+#endif
+
+#include <assert.h>
+#include <iostream>
+#include <iomanip>
+#include <iterator>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <queue>
+#include <vector>
+#include <map>
+#include <set>
+#include <stack>
+#include <list>
+#include <algorithm>
+// #include <cmath>
+// #include <limits>
+// #include <climits>
+
+#if HAVE_PTHREAD_H
+ #include <pthread.h>
+#endif
+
+#include "SmartPointer.h"
+#include "PointerPool.h"
+#include "PoolPointer.h"
+
+typedef uint8_t byte;
+
+namespace Tools
+{
+ SIDX_DLL enum IntervalType
+ {
+ IT_RIGHTOPEN = 0x0,
+ IT_LEFTOPEN,
+ IT_OPEN,
+ IT_CLOSED
+ };
+
+ SIDX_DLL enum VariantType
+ {
+ VT_LONG = 0x0,
+ VT_BYTE,
+ VT_SHORT,
+ VT_FLOAT,
+ VT_DOUBLE,
+ VT_CHAR,
+ VT_USHORT,
+ VT_ULONG,
+ VT_INT,
+ VT_UINT,
+ VT_BOOL,
+ VT_PCHAR,
+ VT_PVOID,
+ VT_EMPTY,
+ VT_LONGLONG,
+ VT_ULONGLONG
+ };
+
+ SIDX_DLL enum FileMode
+ {
+ APPEND = 0x0,
+ CREATE
+ };
+
+ //
+ // Exceptions
+ //
+ class SIDX_DLL Exception
+ {
+ public:
+ virtual std::string what() = 0;
+ virtual ~Exception() {}
+ };
+
+ class SIDX_DLL IndexOutOfBoundsException : public Exception
+ {
+ public:
+ IndexOutOfBoundsException(size_t i);
+ virtual ~IndexOutOfBoundsException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // IndexOutOfBoundsException
+
+ class SIDX_DLL IllegalArgumentException : public Exception
+ {
+ public:
+ IllegalArgumentException(std::string s);
+ virtual ~IllegalArgumentException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // IllegalArgumentException
+
+ class SIDX_DLL IllegalStateException : public Exception
+ {
+ public:
+ IllegalStateException(std::string s);
+ virtual ~IllegalStateException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // IllegalStateException
+
+ class SIDX_DLL EndOfStreamException : public Exception
+ {
+ public:
+ EndOfStreamException(std::string s);
+ virtual ~EndOfStreamException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // EndOfStreamException
+
+ class SIDX_DLL ResourceLockedException : public Exception
+ {
+ public:
+ ResourceLockedException(std::string s);
+ virtual ~ResourceLockedException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // ResourceLockedException
+
+ class SIDX_DLL NotSupportedException : public Exception
+ {
+ public:
+ NotSupportedException(std::string s);
+ virtual ~NotSupportedException() {}
+ virtual std::string what();
+
+ private:
+ std::string m_error;
+ }; // NotSupportedException
+
+ //
+ // Interfaces
+ //
+ class SIDX_DLL IInterval
+ {
+ public:
+ virtual ~IInterval() {}
+
+ virtual double getLowerBound() const = 0;
+ virtual double getUpperBound() const = 0;
+ virtual void setBounds(double, double) = 0;
+ virtual bool intersectsInterval(const IInterval&) const = 0;
+ virtual bool intersectsInterval(IntervalType type, const double start, const double end) const = 0;
+ virtual bool containsInterval(const IInterval&) const = 0;
+ virtual IntervalType getIntervalType() const = 0;
+ }; // IInterval
+
+ class SIDX_DLL IObject
+ {
+ public:
+ virtual ~IObject() {}
+
+ virtual IObject* clone() = 0;
+ // return a new object that is an exact copy of this one.
+ // IMPORTANT: do not return the this pointer!
+ }; // IObject
+
+ class SIDX_DLL ISerializable
+ {
+ public:
+ virtual ~ISerializable() {}
+
+ virtual uint32_t getByteArraySize() = 0;
+ // returns the size of the required byte array.
+ virtual void loadFromByteArray(const byte* data) = 0;
+ // load this object using the byte array.
+ virtual void storeToByteArray(byte** data, uint32_t& length) = 0;
+ // store this object in the byte array.
+ };
+
+ class SIDX_DLL IComparable
+ {
+ public:
+ virtual ~IComparable() {}
+
+ virtual bool operator<(const IComparable& o) const = 0;
+ virtual bool operator>(const IComparable& o) const = 0;
+ virtual bool operator==(const IComparable& o) const = 0;
+ }; //IComparable
+
+ class SIDX_DLL IObjectComparator
+ {
+ public:
+ virtual ~IObjectComparator() {}
+
+ virtual int compare(IObject* o1, IObject* o2) = 0;
+ }; // IObjectComparator
+
+ class SIDX_DLL IObjectStream
+ {
+ public:
+ virtual ~IObjectStream() {}
+
+ virtual IObject* getNext() = 0;
+ // returns a pointer to the next entry in the
+ // stream or 0 at the end of the stream.
+
+ virtual bool hasNext() = 0;
+ // returns true if there are more items in the stream.
+
+ virtual uint32_t size() = 0;
+ // returns the total number of entries available in the stream.
+
+ virtual void rewind() = 0;
+ // sets the stream pointer to the first entry, if possible.
+ }; // IObjectStream
+
+ //
+ // Classes & Functions
+ //
+
+ class SIDX_DLL Variant
+ {
+ public:
+ Variant();
+
+ VariantType m_varType;
+
+ union
+ {
+ int16_t iVal; // VT_SHORT
+ int32_t lVal; // VT_LONG
+ int64_t llVal; // VT_LONGLONG
+ byte bVal; // VT_BYTE
+ float fltVal; // VT_FLOAT
+ double dblVal; // VT_DOUBLE
+ char cVal; // VT_CHAR
+ uint16_t uiVal; // VT_USHORT
+ uint32_t ulVal; // VT_ULONG
+ uint64_t ullVal; // VT_ULONGLONG
+ bool blVal; // VT_BOOL
+ char* pcVal; // VT_PCHAR
+ void* pvVal; // VT_PVOID
+ } m_val;
+ }; // Variant
+
+ class SIDX_DLL PropertySet;
+ SIDX_DLL std::ostream& operator<<(std::ostream& os, const Tools::PropertySet& p);
+
+ class SIDX_DLL PropertySet : public ISerializable
+ {
+ public:
+ PropertySet();
+ PropertySet(const byte* data);
+ virtual ~PropertySet();
+
+ Variant getProperty(std::string property);
+ void setProperty(std::string property, Variant& v);
+ void removeProperty(std::string property);
+
+ virtual uint32_t getByteArraySize();
+ virtual void loadFromByteArray(const byte* data);
+ virtual void storeToByteArray(byte** data, uint32_t& length);
+
+ private:
+ std::map<std::string, Variant> m_propertySet;
+#ifdef HAVE_PTHREAD_H
+ pthread_rwlock_t m_rwLock;
+#else
+ bool m_rwLock;
+#endif
+ friend SIDX_DLL std::ostream& Tools::operator<<(std::ostream& os, const Tools::PropertySet& p);
+ }; // PropertySet
+
+ // does not support degenerate intervals.
+ class SIDX_DLL Interval : public IInterval
+ {
+ public:
+ Interval();
+ Interval(IntervalType, double, double);
+ Interval(double, double);
+ Interval(const Interval&);
+ virtual ~Interval() {}
+ virtual IInterval& operator=(const IInterval&);
+
+ virtual bool operator==(const Interval&) const;
+ virtual bool operator!=(const Interval&) const;
+ virtual double getLowerBound() const;
+ virtual double getUpperBound() const;
+ virtual void setBounds(double, double);
+ virtual bool intersectsInterval(const IInterval&) const;
+ virtual bool intersectsInterval(IntervalType type, const double start, const double end) const;
+ virtual bool containsInterval(const IInterval&) const;
+ virtual IntervalType getIntervalType() const;
+
+ IntervalType m_type;
+ double m_low;
+ double m_high;
+ }; // Interval
+
+ SIDX_DLL std::ostream& operator<<(std::ostream& os, const Tools::Interval& iv);
+
+ class SIDX_DLL Random
+ {
+ public:
+ Random();
+ Random(uint32_t seed, uint16_t xsubi0);
+ virtual ~Random();
+
+ int32_t nextUniformLong();
+ // returns a uniformly distributed long.
+ uint32_t nextUniformUnsignedLong();
+ // returns a uniformly distributed unsigned long.
+ int32_t nextUniformLong(int32_t low, int32_t high);
+ // returns a uniformly distributed long in the range [low, high).
+ uint32_t nextUniformUnsignedLong(uint32_t low, uint32_t high);
+ // returns a uniformly distributed unsigned long in the range [low, high).
+ int64_t nextUniformLongLong();
+ // returns a uniformly distributed long long.
+ uint64_t nextUniformUnsignedLongLong();
+ // returns a uniformly distributed unsigned long long.
+ int64_t nextUniformLongLong(int64_t low, int64_t high);
+ // returns a uniformly distributed unsigned long long in the range [low, high).
+ uint64_t nextUniformUnsignedLongLong(uint64_t low, uint64_t high);
+ // returns a uniformly distributed unsigned long long in the range [low, high).
+ int16_t nextUniformShort();
+ // returns a uniformly distributed short.
+ uint16_t nextUniformUnsignedShort();
+ // returns a uniformly distributed unsigned short.
+ double nextUniformDouble();
+ // returns a uniformly distributed double in the range [0, 1).
+ double nextUniformDouble(double low, double high);
+ // returns a uniformly distributed double in the range [low, high).
+
+ bool flipCoin();
+
+ private:
+ void initDrand(uint32_t seed, uint16_t xsubi0);
+
+ uint16_t* m_pBuffer;
+ }; // Random
+
+ class SIDX_DLL SharedLock
+ {
+ public:
+ #if HAVE_PTHREAD_H
+ SharedLock(pthread_rwlock_t* pLock);
+ ~SharedLock();
+
+ private:
+ pthread_rwlock_t* m_pLock;
+ #endif
+ }; // SharedLock
+
+ class SIDX_DLL ExclusiveLock
+ {
+ public:
+ #if HAVE_PTHREAD_H
+ ExclusiveLock(pthread_rwlock_t* pLock);
+ ~ExclusiveLock();
+
+ private:
+ pthread_rwlock_t* m_pLock;
+ #endif
+ }; // ExclusiveLock
+
+ class SIDX_DLL BufferedFile
+ {
+ public:
+ BufferedFile(uint32_t u32BufferSize = 16384);
+ virtual ~BufferedFile();
+
+ virtual void close();
+ virtual bool eof();
+ virtual void rewind() = 0;
+ virtual void seek(std::fstream::off_type offset) = 0;
+
+ protected:
+ std::fstream m_file;
+ char* m_buffer;
+ uint32_t m_u32BufferSize;
+ bool m_bEOF;
+ };
+
+ class SIDX_DLL BufferedFileReader : public BufferedFile
+ {
+ public:
+ BufferedFileReader();
+ BufferedFileReader(const std::string& sFileName, uint32_t u32BufferSize = 32768);
+ virtual ~BufferedFileReader();
+
+ virtual void open(const std::string& sFileName);
+ virtual void rewind();
+ virtual void seek(std::fstream::off_type offset);
+
+ virtual uint8_t readUInt8();
+ virtual uint16_t readUInt16();
+ virtual uint32_t readUInt32();
+ virtual uint64_t readUInt64();
+ virtual float readFloat();
+ virtual double readDouble();
+ virtual bool readBoolean();
+ virtual std::string readString();
+ virtual void readBytes(uint32_t u32Len, byte** pData);
+ };
+
+ class SIDX_DLL BufferedFileWriter : public BufferedFile
+ {
+ public:
+ BufferedFileWriter();
+ BufferedFileWriter(const std::string& sFileName, FileMode mode = CREATE, uint32_t u32BufferSize = 32768);
+ virtual ~BufferedFileWriter();
+
+ virtual void open(const std::string& sFileName, FileMode mode = CREATE);
+ virtual void rewind();
+ virtual void seek(std::fstream::off_type offset);
+
+ virtual void write(uint8_t i);
+ virtual void write(uint16_t i);
+ virtual void write(uint32_t i);
+ virtual void write(uint64_t i);
+ virtual void write(float i);
+ virtual void write(double i);
+ virtual void write(bool b);
+ virtual void write(const std::string& s);
+ virtual void write(uint32_t u32Len, byte* pData);
+ };
+
+ class SIDX_DLL TemporaryFile
+ {
+ public:
+ TemporaryFile();
+ virtual ~TemporaryFile();
+
+ void rewindForReading();
+ void rewindForWriting();
+ bool eof();
+ std::string getFileName() const;
+
+ uint8_t readUInt8();
+ uint16_t readUInt16();
+ uint32_t readUInt32();
+ uint64_t readUInt64();
+ float readFloat();
+ double readDouble();
+ std::string readString();
+ void readBytes(uint32_t u32Len, byte** pData);
+
+ void write(uint8_t i);
+ void write(uint16_t i);
+ void write(uint32_t i);
+ void write(uint64_t i);
+ void write(float i);
+ void write(double i);
+ void write(const std::string& s);
+ void write(uint32_t u32Len, byte* pData);
+
+ private:
+ std::string m_sFile;
+ BufferedFile* m_pFile;
+ };
+}
+
diff --git a/sci-libs/libspatialindex/svn/trunk/include/tools/rand48.h b/sci-libs/libspatialindex/svn/trunk/include/tools/rand48.h new file mode 100644 index 000000000..fd2063ef7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/include/tools/rand48.h @@ -0,0 +1,11 @@ +#pragma once + +extern void srand48(long seed); +extern unsigned short *seed48(unsigned short xseed[3]); +extern long nrand48(unsigned short xseed[3]); +extern long mrand48(void); +extern long lrand48(void); +extern void lcong48(unsigned short p[7]); +extern long jrand48(unsigned short xseed[3]); +extern double erand48(unsigned short xseed[3]); +extern double drand48(void); diff --git a/sci-libs/libspatialindex/svn/trunk/install-sh b/sci-libs/libspatialindex/svn/trunk/install-sh new file mode 100755 index 000000000..dd97db7aa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/install-sh @@ -0,0 +1,322 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-09-10.20 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/makefile.vc b/sci-libs/libspatialindex/svn/trunk/makefile.vc new file mode 100644 index 000000000..6d018a383 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/makefile.vc @@ -0,0 +1,217 @@ + +.SUFFIXES: .cc + +SPATIALINDEX_HOME=c:\cvs\buildkit\spatialindex +DLL_VERSION = 1 + +BINDIR=$(SPATIALINDEX_HOME)\bin +OSGEO4W_DIR = $(SPATIALINDEX_HOME)\osgeo4w + + +############################################################################### +# Set BUILD_DEBUG balue to YES if you want to make debug build +# and to prepare not optimized binaries. +!IFNDEF BUILD_DEBUG +BUILD_DEBUG = NO +!ENDIF + + +############################################################################### +# Derive version of Visual C++ being used from NMAKE if not specified +# +# WARNING: +# If we should expect variety of NMAKE build versions, tests below may fail +# and we will need to fall back to setting MSVCVER as command line parameter. +# +!IF "$(_NMAKE_VER)" == "" +MSVCVER = 4.0 +!ERROR *** Failed to determine version of Visual C++ +!ELSEIF "$(_NMAKE_VER)" == "162" +MSVCVER = 5.0 +!ERROR *** Detected Visual C++ 5.0 - NOT SUPPORTED +!ELSEIF "$(_NMAKE_VER)" == "6.00.8168.0" +MSVCVER = 6.0 +!ERROR *** Detected Visual C++ 6.0 - NOT SUPPORTED +!ELSEIF "$(_NMAKE_VER)" == "7.00.9466" +MSVCVER = 7.0 +!ELSEIF "$(_NMAKE_VER)" == "7.10.3077" +MSVCVER = 7.1 +!ELSEIF "$(_NMAKE_VER)" == "8.00.50727.42" +MSVCVER = 8.0 +!ELSEIF "$(_NMAKE_VER)" == "8.00.50727.762" +MSVCVER = 8.0 +!ELSEIF "$(_NMAKE_VER)" == "9.00.21022.08" +MSVCVER = 9.0 +!ELSEIF "$(_NMAKE_VER)" == "9.00.30729.01" +MSVCVER = 9.0 +!ELSE +MSVCVER = 0.0 +!ENDIF + +!IF "$(MSVCVER)" == "0.0" +!MESSAGE *** Cannot determined Visual C++ version +!ERROR *** Aborting make job +!ELSE +!MESSAGE *** Using Microsoft NMAKE version $(_NMAKE_VER) +!MESSAGE *** Using Microsoft Visual C++ version $(MSVCVER) +!ENDIF + +############################################################################### +# Compilation flags for Release and Debug modes + +!IF "$(BUILD_DEBUG)" == "YES" +OPTFLAGS=/nologo /MDd /EHsc /Z7 /W4 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /DDEBUG /D_DEBUG /DDEBUG /Fd$(SPATIALINDEX_HOME)\spatialindex.pdb +LAS_LIB = spatialindex_d.lib +LAS_DLL = spatialindex_d$(DLL_VERSION).dll +LAS_LIB_DLL = spatialindex_i.lib +!ELSE + +# You may need to remove /GR if you are statically linking libLAS +OPTFLAGS=/nologo /MD /EHsc /Ox /GR /W2 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /DNDEBUG /D "PACKAGE_BUGREPORT=\"hobu.inc@gmail.com\"" /DSPATIALINDEX_CREATE_DLL=1 +LAS_LIB = spatialindex.lib +LAS_DLL = spatialindex$(DLL_VERSION).dll +CDLLNAME = spatialindex$(DLL_VERSION)_c.dll +CLIBNAME = spatialindex_c_i.lib +LAS_LIB_DLL = spatialindex_i.lib +!ENDIF + +# Check if multiple process build available +!IF "$(MSVCVER)" == "9.0" +MPFLAGS=/MP +!MESSAGE *** Using /MP flag with number of effective processors +!ELSE +MPFLAGS= +!ENDIF + +PACKAGE_VERSION=1.6.1 + +INCLUDES=-I$(SPATIALINDEX_HOME)/include -I$(SPATIALINDEX_HOME)/include/capi +CFLAGS= $(MPFLAGS) $(OPTFLAGS) $(INCLUDES) + + +# Commands +# +MAKE = nmake +RM = -del +CC= cl +LINK= link + +LAS_DIRLIST = src\mvrtree \ + src\rtree \ + src\spatialindex \ + src\storagemanager \ + src\tools \ + src\tprtree \ + src\capi + +OBJS = src\mvrtree\Index.obj \ + src\mvrtree\Leaf.obj \ + src\mvrtree\MVRtree.obj \ + src\mvrtree\Node.obj \ + src\mvrtree\Statistics.obj \ + src\rtree\BulkLoader.obj \ + src\rtree\Index.obj \ + src\rtree\Leaf.obj \ + src\rtree\Node.obj \ + src\rtree\RTree.obj \ + src\rtree\Statistics.obj \ + src\spatialindex\LineSegment.obj \ + src\spatialindex\MovingPoint.obj \ + src\spatialindex\MovingRegion.obj \ + src\spatialindex\Point.obj \ + src\spatialindex\Region.obj \ + src\spatialindex\SpatialIndexImpl.obj \ + src\spatialindex\TimePoint.obj \ + src\spatialindex\TimeRegion.obj \ + src\storagemanager\Buffer.obj \ + src\storagemanager\DiskStorageManager.obj \ + src\storagemanager\MemoryStorageManager.obj \ + src\storagemanager\RandomEvictionsBuffer.obj \ + src\tools\rand48.obj \ + src\tools\Tools.obj \ + src\tprtree\Index.obj \ + src\tprtree\Leaf.obj \ + src\tprtree\Node.obj \ + src\tprtree\Statistics.obj \ + src\tprtree\TPRTree.obj + +COBJS = src\capi\BoundsQuery.obj \ + src\capi\CountVisitor.obj \ + src\capi\CustomStorage.obj \ + src\capi\DataStream.obj \ + src\capi\Error.obj \ + src\capi\IdVisitor.obj \ + src\capi\Index.obj \ + src\capi\LeafQuery.obj \ + src\capi\ObjVisitor.obj \ + src\capi\sidx_api.obj\ + src\capi\Utility.obj + +default: $(LAS_DLL) $(CDLLNAME) + +all: default + + +$(LAS_LIB): $(OBJS) + if exist $(LAS_LIB) del $(LAS_LIB) + $(LINK) /lib /nologo /out:$(LAS_LIB) $(OBJS) + +$(LAS_DLL): $(LAS_LIB) $(RES) + $(LINK) /dll \ + $(OBJS) $(LAS_LIB) \ + /out:$(LAS_DLL) /implib:$(LAS_LIB_DLL) + if exist $(LAS_DLL).manifest mt -manifest $(LAS_DLL).manifest -outputresource:$(LAS_DLL);2 + +$(CDLLNAME): $(COBJS) $(LAS_DLL) + $(LINK) /dll /debug $(COBJS) $(LAS_LIB_DLL) /out:$(CDLLNAME) /implib:$(CLIBNAME) + if exist $(CDLLNAME).manifest mt -manifest $(CDLLNAME).manifest -outputresource:$(CDLLNAME);2 + + +install: default + -mkdir $(BINDIR) + -mkdir $(SPATIALINDEX_HOME)\packages + -mkdir $(BINDIR)\lib + -mkdir $(BINDIR)\include\spatialindex + -mkdir $(OSGEO4W_DIR) + -mkdir $(OSGEO4W_DIR)\lib + -mkdir $(OSGEO4W_DIR)\devel + -mkdir $(OSGEO4W_DIR)\lib\bin + -mkdir $(OSGEO4W_DIR)\devel\include + -mkdir $(OSGEO4W_DIR)\devel\include\spatialindex + -mkdir $(OSGEO4W_DIR)\devel\lib + xcopy /y /r /d /f spatialindex_i.lib $(BINDIR)\lib + xcopy /y /r /d /f spatialindex_i.lib $(OSGEO4W_DIR)\devel\lib + xcopy /y /r /d /f spatialindex.lib $(BINDIR)\lib + xcopy /y /r /d /f spatialindex.lib $(OSGEO4W_DIR)\devel\lib + xcopy /y /r /d /f /s include\* $(BINDIR)\include\spatialindex + xcopy /y /r /d /f /s include\* $(OSGEO4W_DIR)\devel\include\spatialindex + xcopy /y /r /d /f $(LAS_DLL) $(BINDIR) + xcopy /y /r /d /f $(LAS_DLL) $(OSGEO4W_DIR)\lib\bin + +.cc.obj: + $(CC) $(CFLAGS) /c $*.cc /Fo$@ + +.c.obj: + $(CC) $(CFLAGS) /c $*.c /Fo$@ + +clean: + $(RM) $(LAS_LIB) + $(RM) $(LAS_DLL) + $(RM) *.ilk + $(RM) *.manifest + $(RM) *.obj + $(RM) *.pdb + for %d in ( $(LAS_DIRLIST) ) do \ + del %d\*.obj + +package: install + cd $(SPATIALINDEX_HOME)/osgeo4w/lib + C:\cygwin\bin\tar.exe cvf ../../packages/libspatialindex-$(PACKAGE_VERSION).tar * + c:\cygwin\bin\bzip2.exe -f /cygdrive/c/cvs/buildkit/spatialindex/packages/libspatialindex-$(PACKAGE_VERSION).tar + cd $(SPATIALINDEX_HOME)/osgeo4w/ + cd $(SPATIALINDEX_HOME)/osgeo4w/devel + C:\cygwin\bin\tar.exe cvf ../../packages/libspatialindex-devel-$(PACKAGE_VERSION).tar * + c:\cygwin\bin\bzip2.exe -f /cygdrive/c/cvs/buildkit/spatialindex/packages/libspatialindex-devel-$(PACKAGE_VERSION).tar + cd $(SPATIALINDEX_HOME)/osgeo4w/ + cd $(SPATIALINDEX_HOME)/ + c:\cygwin\bin\zip.exe -r packages/libspatialindex-$(PACKAGE_VERSION)-win32.zip bin diff --git a/sci-libs/libspatialindex/svn/trunk/missing b/sci-libs/libspatialindex/svn/trunk/missing new file mode 100644 index 000000000..64b5f901d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/missing @@ -0,0 +1,353 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to <bug-automake@gnu.org>." + exit 0 + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit 0 + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/mkinstalldirs b/sci-libs/libspatialindex/svn/trunk/mkinstalldirs new file mode 100755 index 000000000..6fbe5e117 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/mkinstalldirs @@ -0,0 +1,150 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2004-02-15.20 + +# Original author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to <bug-automake@gnu.org>." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit 0 + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/all-wcprops new file mode 100644 index 000000000..bda49c2b9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 60 +/spatialindex/!svn/ver/182/spatialindex/trunk/regressiontest +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/Makefile.am +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/dir-prop-base new file mode 100644 index 000000000..a57f5442b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 21 +Makefile +Makefile.in + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/entries new file mode 100644 index 000000000..fe126ca06 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/entries @@ -0,0 +1,71 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest +http://svn.gispython.org/spatialindex + + + +2010-04-12T17:17:47.459585Z +182 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +rtree +dir + +mvrtree +dir + +tprtree +dir + +Makefile.am +file + + + + +2011-08-01T00:42:34.161195Z +a1b35b54bda110ef312d7f2b23d61b3f +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +105 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..555767682 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,2 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +SUBDIRS = rtree mvrtree tprtree diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/Makefile.am b/sci-libs/libspatialindex/svn/trunk/regressiontest/Makefile.am new file mode 100644 index 000000000..555767682 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/Makefile.am @@ -0,0 +1,2 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +SUBDIRS = rtree mvrtree tprtree diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/all-wcprops new file mode 100644 index 000000000..34202bd6c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/all-wcprops @@ -0,0 +1,35 @@ +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/171/spatialindex/trunk/regressiontest/mvrtree +END +MVRTreeLoad.cc +K 25 +svn:wc:ra_dav:version-url +V 82 +/spatialindex/!svn/ver/90/spatialindex/trunk/regressiontest/mvrtree/MVRTreeLoad.cc +END +Exhaustive.cc +K 25 +svn:wc:ra_dav:version-url +V 82 +/spatialindex/!svn/ver/171/spatialindex/trunk/regressiontest/mvrtree/Exhaustive.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 78 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/mvrtree/Makefile.am +END +Generator.cc +K 25 +svn:wc:ra_dav:version-url +V 81 +/spatialindex/!svn/ver/159/spatialindex/trunk/regressiontest/mvrtree/Generator.cc +END +MVRTreeQuery.cc +K 25 +svn:wc:ra_dav:version-url +V 83 +/spatialindex/!svn/ver/90/spatialindex/trunk/regressiontest/mvrtree/MVRTreeQuery.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/dir-prop-base new file mode 100644 index 000000000..42643052a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/dir-prop-base @@ -0,0 +1,13 @@ +K 10 +svn:ignore +V 79 +Makefile.in +MVRTreeLoad +Exhaustive +Generator +.libs +.deps +MVRTreeQuery +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/entries new file mode 100644 index 000000000..04525f3aa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/entries @@ -0,0 +1,204 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/mvrtree +http://svn.gispython.org/spatialindex + + + +2009-12-29T02:35:01.217521Z +171 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +test1 +dir + +test2 +dir + +MVRTreeLoad.cc +file + + + + +2011-08-01T00:42:34.101428Z +76ba58f70f4c319c96fbf89fbb0602d4 +2009-05-04T17:10:20.890704Z +90 +hobu + + + + + + + + + + + + + + + + + + + + + +6439 + +Exhaustive.cc +file + + + + +2011-08-01T00:42:34.101428Z +acea00cc466cbd5c29c44b202e2afa5f +2009-12-29T02:35:01.217521Z +171 +hobu + + + + + + + + + + + + + + + + + + + + + +5419 + +Makefile.am +file + + + + +2011-08-01T00:42:34.101428Z +1e94b0b0a67c7e0ddc2847eb564da76a +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +492 + +Generator.cc +file + + + + +2011-08-01T00:42:34.101428Z +2a7d166c94bbd2157757920195dac6f4 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +5705 + +MVRTreeQuery.cc +file + + + + +2011-08-01T00:42:34.101428Z +1754e0a954b06cf1038209bb65f2c798 +2009-05-04T17:10:20.890704Z +90 +hobu + + + + + + + + + + + + + + + + + + + + + +6570 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Exhaustive.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Exhaustive.cc.svn-base new file mode 100644 index 000000000..b73fdf74e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Exhaustive.cc.svn-base @@ -0,0 +1,225 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <assert.h> +#include <iostream> +#include <fstream> +#include <map> +#include <queue> +#include <cmath> +#include <cstring> +#include <limits> +#include <cmath> +#include <stdint.h> + +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + +// Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html +#pragma warning( disable: 4251 ) + +#else + #include <stdint.h> +#endif + +class TimeRegion +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + double m_startTime, m_endTime; + + TimeRegion() {} + + TimeRegion(double x1, double y1, double x2, double y2, double t1, double t2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + m_startTime = t1; + m_endTime = (t2 <= 0) ? std::numeric_limits<double>::max() : t2; + } + + bool intersects(TimeRegion& r) + { + if (m_xmin > r.m_xmax || m_xmax < r.m_xmin || + m_ymin > r.m_ymax || m_ymax < r.m_ymin) return false; + + return true; + } + + bool intersectsInTime(TimeRegion& r) + { + //if (m_startTime != r.m_startTime && (m_endTime <= r.m_startTime || m_startTime >= r.m_endTime)) return false; + if (m_endTime <= r.m_startTime || m_startTime >= r.m_endTime) return false; + return intersects(r); + } + + double getMinDist(const TimeRegion& r) + { + double ret = 0.0; + + if (r.m_xmax < m_xmin) + ret += std::pow(m_xmin - r.m_xmax, 2.0); + else if (r.m_xmin > m_xmax) + ret += std::pow(r.m_xmin - m_xmax, 2.0); + + if (r.m_ymax < m_ymin) + ret += std::pow(m_ymin - r.m_ymax, 2.0); + else if (r.m_ymin > m_ymax) + ret += std::pow(r.m_ymin - m_ymax, 2.0); + + return ret; + } +}; + +class NNEntry +{ +public: + size_t m_id; + double m_dist; + + NNEntry(size_t id, double dist) : m_id(id), m_dist(dist) {} + + struct greater : public binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_dist > __y->m_dist; } + }; +}; + +int main(int argc, char** argv) +{ + if (argc != 3) + { + cerr << "Usage: " << argv[0] << " data_file query_type [intersection | 10NN]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[2], "intersection") == 0) queryType = 0; + else if (strcmp(argv[2], "10NN") == 0) queryType = 1; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file" << argv[1] << "." << endl; + return -1; + } + + multimap<size_t, TimeRegion> data; + size_t id; + uint32_t op; + double x1, x2, y1, y2, t; + + while (fin) + { + fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; + + if (op == INSERT) + { + //insert + data.insert(pair<size_t, TimeRegion>(id, TimeRegion(x1, y1, x2, y2, t, std::numeric_limits<double>::max()))); + } + else if (op == DELETE) + { + //delete + // find the live instance of id. + multimap<size_t, TimeRegion>::iterator it = data.find(id); + assert(it != data.end()); + while (it->first == id && it->second.m_endTime < std::numeric_limits<double>::max()) it++; + assert(it->first == id); + (*it).second.m_endTime = t; + } + else if (op == QUERY) + { + size_t qt1, qt2; + fin >> qt1 >> qt2; + if (! fin.good()) continue; + + //query + if (queryType == 0) + { + TimeRegion query = TimeRegion(x1, y1, x2, y2, qt1, qt2); + for (multimap<size_t, TimeRegion>::iterator it = data.begin(); it != data.end(); it++) + { + if (query.intersectsInTime((*it).second)) cout << (*it).first << endl; + } + } + else + { + /* + TimeRegion query = TimeRegion(x1, y1, x1, y1, qt1, qt2); + + priority_queue<NNEntry*, vector<NNEntry*>, NNEntry::greater > queue; + + for (multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + queue.push(new NNEntry((*it).first, (*it).second.getMinDist(query))); + } + + size_t count = 0; + double knearest = 0.0; + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + + if (count >= 10 && e->m_dist > knearest) break; + + //cout << e->m_id << " " << e->m_dist << endl; + cout << e->m_id << endl; + count++; + knearest = e->m_dist; + delete e; + } + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + delete e; + } + */ + } + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Generator.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Generator.cc.svn-base new file mode 100644 index 000000000..288684c69 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Generator.cc.svn-base @@ -0,0 +1,175 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <tools/Tools.h> +#include <cmath> +#include <limits> + +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +class Region +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + bool m_bIsDead; + + Region() : m_xmin(numeric_limits<double>::max()), m_ymin(numeric_limits<double>::max()), + m_xmax(numeric_limits<double>::max()), m_ymax(numeric_limits<double>::max()) {} + + Region(double x1, double y1, double x2, double y2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + m_bIsDead = false; + } +}; + +int main(int argc, char** argv) +{ + if (argc != 2) + { + cerr << "Usage: " << argv[0] << " number_of_data." << endl; + return -1; + } + + size_t numberOfObjects = atoi(argv[1]); + map<size_t, Region> data; + Tools::Random rnd; + + for (size_t i = 0; i < numberOfObjects; i++) + { + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(pair<size_t, Region>(i, r)); + + cout << "0 " << INSERT << " " << i << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << endl; + } + + size_t nextID = numberOfObjects; + size_t A = static_cast<size_t>(std::floor(static_cast<double>(numberOfObjects) * 0.05)); + + for (size_t T = 1; T <= 100; T++) + { + cerr << (101 - T) << endl; + + if (T == 50) + { + // delete all entries and reinsert + for (map<size_t, Region>::iterator itMap = data.begin(); itMap != data.end(); itMap++) + { + if (! (*itMap).second.m_bIsDead) + { + (*itMap).second.m_bIsDead = true; + cout << "50 " << DELETE << " " << (*itMap).first << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << endl; + } + } + + for (size_t i = nextID; i < nextID + numberOfObjects; i++) + { + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(pair<size_t, Region>(i, r)); + + cout << "50 " << INSERT << " " << i << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << endl; + } + + nextID += numberOfObjects; + continue; + } + + set<size_t> examined; + + for (size_t a = 0; a < A; a++) + { + // find an id that is not examined yet. + size_t id = static_cast<size_t>(rnd.nextUniformLongLong(0, nextID)); + set<size_t>::iterator itSet = examined.find(id); + while (itSet != examined.end() || data[id].m_bIsDead == true) + { + id = static_cast<size_t>(rnd.nextUniformLongLong(0, nextID)); + itSet = examined.find(id); + } + examined.insert(id); + + map<size_t, Region>::iterator itMap = data.find(id); + assert(itMap != data.end() && (*itMap).second.m_bIsDead == false); + + cout << T << " " << DELETE << " " << id << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << endl; + (*itMap).second.m_bIsDead = true; + + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(pair<size_t, Region>(nextID, r)); + + cout << T << " " << INSERT << " " << nextID << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << endl; + examined.insert(nextID); + nextID++; + } + + double stx = rnd.nextUniformDouble(); + double sty = rnd.nextUniformDouble(); + size_t qt = rnd.nextUniformLongLong(0, T); + cout << T << " " << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << " " << qt << " " << qt + 2<< endl; + stx = rnd.nextUniformDouble(); + sty = rnd.nextUniformDouble(); + qt = rnd.nextUniformLongLong(0, T); + cout << T << " " << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << " " << qt << " " << qt + 2<< endl; + stx = rnd.nextUniformDouble(); + sty = rnd.nextUniformDouble(); + qt = rnd.nextUniformLongLong(0, T); + cout << T << " " << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << " " << qt << " " << qt + 2<< endl; + } + + // delete everything at the end (for testing the special case when the tree dies out completely) + for (map<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + if (! it->second.m_bIsDead) + { + cout << 102 << " " << DELETE << " " << it->first << " " << it->second.m_xmin << " " << it->second.m_ymin << " " + << it->second.m_xmax << " " << it->second.m_ymax << endl; + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/MVRTreeLoad.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/MVRTreeLoad.cc.svn-base new file mode 100644 index 000000000..7e07e2731 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/MVRTreeLoad.cc.svn-base @@ -0,0 +1,209 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +// example of a Visitor pattern. +// see MVRTreeQuery for a more elaborate example. +class MyVisitor : public IVisitor +{ +public: + void visitNode(const INode& n) {} + + void visitData(const IData& d) + { + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 5) + { + cerr << "Usage: " << argv[0] << " input_file tree_file capacity query_type [intersection | 10NN]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[4], "intersection") == 0) queryType = 0; + else if (strcmp(argv[4], "10NN") == 0) queryType = 1; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file " << argv[1] << "." << endl; + return -1; + } + + // Create a new storage manager with the provided base name and a 4K page size. + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + //StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // Create a new, empty, MVRTree with dimensionality 2, minimum load 70%, using "file" as + // the StorageManager and the RSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = MVRTree::createNewMVRTree(*diskfile, 0.7, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::MVRTree::RV_RSTAR, indexIdentifier); + + size_t count = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2, t; + double plow[2], phigh[2]; + + while (fin) + { + fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + TimeRegion r = TimeRegion(plow, phigh, t, t, 2); + + //ostringstream os; + //os << r; + //string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see MVRTree::Node::load and MVRTree::Node::store for + // an example of how to do that). + + //tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + TimeRegion r = TimeRegion(plow, phigh, t, t, 2); + + if (tree->deleteData(r, id) == false) + { + cerr << "******ERROR******" << endl; + cerr << "Cannot delete id: " << id << " , count: " << count << endl; + return -1; + } + } + else if (op == QUERY) + { + size_t qt1, qt2; + fin >> qt1 >> qt2; + if (! fin.good()) continue; + + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + TimeRegion r = TimeRegion(plow, phigh, qt1, qt2, 2); + + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else + { + //Point p = Point(plow, 2); + //tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + cerr << "Operations: " << count << endl; + cerr << *tree; + //cerr << "Buffer hits: " << file->getHits() << endl; + cerr << "Index ID: " << indexIdentifier << endl; + + bool ret = tree->isIndexValid(); + if (ret == false) cerr << "ERROR: Structure is invalid!" << endl; + else cerr << "The stucture seems O.K." << endl; + + delete tree; + //delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/MVRTreeQuery.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/MVRTreeQuery.cc.svn-base new file mode 100644 index 000000000..f8e367bc7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/MVRTreeQuery.cc.svn-base @@ -0,0 +1,268 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +// example of a Visitor pattern. +// findes the index and leaf IO for answering the query and prints +// the resulting data IDs to stdout. +class MyVisitor : public IVisitor +{ +public: + size_t m_indexIO; + size_t m_leafIO; + +public: + MyVisitor() : m_indexIO(0), m_leafIO(0) {} + + void visitNode(const INode& n) + { + if (n.isLeaf()) m_leafIO++; + else m_indexIO++; + } + + void visitData(const IData& d) + { + //IShape* pS; + //d.getShape(&pS); + // do something. + //delete pS; + + // data should be an array of characters representing a Region as a string. + //byte* pData = 0; + //size_t cLen = 0; + //d.getData(cLen, &pData); + // do something. + //string s = reinterpret_cast<char*>(pData); + //cout << s << endl; + //delete[] pData; + + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +// example of a Strategy pattern. +// traverses the tree by level. +class MyQueryStrategy : public SpatialIndex::IQueryStrategy +{ +private: + queue<id_type> ids; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + IShape* ps; + entry.getShape(&ps); + Region* pr = dynamic_cast<Region*>(ps); + + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl << endl << endl; + // print node MBRs gnuplot style! + + delete ps; + + const INode* n = dynamic_cast<const INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 1) + { + for (size_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push(n->getChildIdentifier(cChild)); + } + } + + if (! ids.empty()) + { + nextEntry = ids.front(); ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } + } +}; + +// example of a Strategy pattern. +// find the total indexed space managed by the index (the MBR of the root). +class MyQueryStrategy2 : public IQueryStrategy +{ +public: + Region m_indexedSpace; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + // the first time we are called, entry points to the root. + + // stop after the root. + hasNext = false; + + IShape* ps; + entry.getShape(&ps); + ps->getMBR(m_indexedSpace); + delete ps; + } +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 4) + { + cerr << "Usage: " << argv[0] << " query_file tree_file query_type [intersection | 10NN]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[3], "intersection") == 0) queryType = 0; + else if (strcmp(argv[3], "10NN") == 0) queryType = 1; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open query file " << argv[1] << "." << endl; + return -1; + } + + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::loadDiskStorageManager(baseName); + // this will try to locate and open an already existing storage manager. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // If we need to open an existing tree stored in the storage manager, we only + // have to specify the index identifier as follows + ISpatialIndex* tree = MVRTree::loadMVRTree(*file, 1); + + size_t count = 0; + size_t indexIO = 0; + size_t leafIO = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2, t; + double plow[2], phigh[2]; + + while (fin) + { + fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == QUERY) + { + size_t qt1, qt2; + fin >> qt1 >> qt2; + if (! fin.good()) continue; + + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + TimeRegion r = TimeRegion(plow, phigh, qt1, qt2, 2); + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else + { + //Point p = Point(plow, 2); + //tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + + indexIO += vis.m_indexIO; + leafIO += vis.m_leafIO; + // example of the Visitor pattern usage, for calculating how many nodes + // were visited. + } + else + { + cerr << "This is not a query operation." << endl; + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + MyQueryStrategy2 qs; + tree->queryStrategy(qs); + + cerr << "Indexed space: " << qs.m_indexedSpace << endl; + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Index I/O: " << indexIO << endl; + cerr << "Leaf I/O: " << leafIO << endl; + cerr << "Buffer hits: " << file->getHits() << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail writting the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..77a83a1e3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,12 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_PROGRAMS = Generator Exhaustive MVRTreeLoad MVRTreeQuery +INCLUDES = -I../../include +Generator_SOURCES = Generator.cc +Generator_LDADD = ../../libspatialindex.la +Exhaustive_SOURCES = Exhaustive.cc +Exhaustive_LDADD = ../../libspatialindex.la +MVRTreeLoad_SOURCES = MVRTreeLoad.cc +MVRTreeLoad_LDADD = ../../libspatialindex.la +MVRTreeQuery_SOURCES = MVRTreeQuery.cc +MVRTreeQuery_LDADD = ../../libspatialindex.la + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Exhaustive.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Exhaustive.cc new file mode 100644 index 000000000..b73fdf74e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Exhaustive.cc @@ -0,0 +1,225 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <assert.h> +#include <iostream> +#include <fstream> +#include <map> +#include <queue> +#include <cmath> +#include <cstring> +#include <limits> +#include <cmath> +#include <stdint.h> + +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + +// Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html +#pragma warning( disable: 4251 ) + +#else + #include <stdint.h> +#endif + +class TimeRegion +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + double m_startTime, m_endTime; + + TimeRegion() {} + + TimeRegion(double x1, double y1, double x2, double y2, double t1, double t2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + m_startTime = t1; + m_endTime = (t2 <= 0) ? std::numeric_limits<double>::max() : t2; + } + + bool intersects(TimeRegion& r) + { + if (m_xmin > r.m_xmax || m_xmax < r.m_xmin || + m_ymin > r.m_ymax || m_ymax < r.m_ymin) return false; + + return true; + } + + bool intersectsInTime(TimeRegion& r) + { + //if (m_startTime != r.m_startTime && (m_endTime <= r.m_startTime || m_startTime >= r.m_endTime)) return false; + if (m_endTime <= r.m_startTime || m_startTime >= r.m_endTime) return false; + return intersects(r); + } + + double getMinDist(const TimeRegion& r) + { + double ret = 0.0; + + if (r.m_xmax < m_xmin) + ret += std::pow(m_xmin - r.m_xmax, 2.0); + else if (r.m_xmin > m_xmax) + ret += std::pow(r.m_xmin - m_xmax, 2.0); + + if (r.m_ymax < m_ymin) + ret += std::pow(m_ymin - r.m_ymax, 2.0); + else if (r.m_ymin > m_ymax) + ret += std::pow(r.m_ymin - m_ymax, 2.0); + + return ret; + } +}; + +class NNEntry +{ +public: + size_t m_id; + double m_dist; + + NNEntry(size_t id, double dist) : m_id(id), m_dist(dist) {} + + struct greater : public binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_dist > __y->m_dist; } + }; +}; + +int main(int argc, char** argv) +{ + if (argc != 3) + { + cerr << "Usage: " << argv[0] << " data_file query_type [intersection | 10NN]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[2], "intersection") == 0) queryType = 0; + else if (strcmp(argv[2], "10NN") == 0) queryType = 1; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file" << argv[1] << "." << endl; + return -1; + } + + multimap<size_t, TimeRegion> data; + size_t id; + uint32_t op; + double x1, x2, y1, y2, t; + + while (fin) + { + fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; + + if (op == INSERT) + { + //insert + data.insert(pair<size_t, TimeRegion>(id, TimeRegion(x1, y1, x2, y2, t, std::numeric_limits<double>::max()))); + } + else if (op == DELETE) + { + //delete + // find the live instance of id. + multimap<size_t, TimeRegion>::iterator it = data.find(id); + assert(it != data.end()); + while (it->first == id && it->second.m_endTime < std::numeric_limits<double>::max()) it++; + assert(it->first == id); + (*it).second.m_endTime = t; + } + else if (op == QUERY) + { + size_t qt1, qt2; + fin >> qt1 >> qt2; + if (! fin.good()) continue; + + //query + if (queryType == 0) + { + TimeRegion query = TimeRegion(x1, y1, x2, y2, qt1, qt2); + for (multimap<size_t, TimeRegion>::iterator it = data.begin(); it != data.end(); it++) + { + if (query.intersectsInTime((*it).second)) cout << (*it).first << endl; + } + } + else + { + /* + TimeRegion query = TimeRegion(x1, y1, x1, y1, qt1, qt2); + + priority_queue<NNEntry*, vector<NNEntry*>, NNEntry::greater > queue; + + for (multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + queue.push(new NNEntry((*it).first, (*it).second.getMinDist(query))); + } + + size_t count = 0; + double knearest = 0.0; + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + + if (count >= 10 && e->m_dist > knearest) break; + + //cout << e->m_id << " " << e->m_dist << endl; + cout << e->m_id << endl; + count++; + knearest = e->m_dist; + delete e; + } + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + delete e; + } + */ + } + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Generator.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Generator.cc new file mode 100644 index 000000000..288684c69 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Generator.cc @@ -0,0 +1,175 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <tools/Tools.h> +#include <cmath> +#include <limits> + +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +class Region +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + bool m_bIsDead; + + Region() : m_xmin(numeric_limits<double>::max()), m_ymin(numeric_limits<double>::max()), + m_xmax(numeric_limits<double>::max()), m_ymax(numeric_limits<double>::max()) {} + + Region(double x1, double y1, double x2, double y2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + m_bIsDead = false; + } +}; + +int main(int argc, char** argv) +{ + if (argc != 2) + { + cerr << "Usage: " << argv[0] << " number_of_data." << endl; + return -1; + } + + size_t numberOfObjects = atoi(argv[1]); + map<size_t, Region> data; + Tools::Random rnd; + + for (size_t i = 0; i < numberOfObjects; i++) + { + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(pair<size_t, Region>(i, r)); + + cout << "0 " << INSERT << " " << i << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << endl; + } + + size_t nextID = numberOfObjects; + size_t A = static_cast<size_t>(std::floor(static_cast<double>(numberOfObjects) * 0.05)); + + for (size_t T = 1; T <= 100; T++) + { + cerr << (101 - T) << endl; + + if (T == 50) + { + // delete all entries and reinsert + for (map<size_t, Region>::iterator itMap = data.begin(); itMap != data.end(); itMap++) + { + if (! (*itMap).second.m_bIsDead) + { + (*itMap).second.m_bIsDead = true; + cout << "50 " << DELETE << " " << (*itMap).first << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << endl; + } + } + + for (size_t i = nextID; i < nextID + numberOfObjects; i++) + { + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(pair<size_t, Region>(i, r)); + + cout << "50 " << INSERT << " " << i << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << endl; + } + + nextID += numberOfObjects; + continue; + } + + set<size_t> examined; + + for (size_t a = 0; a < A; a++) + { + // find an id that is not examined yet. + size_t id = static_cast<size_t>(rnd.nextUniformLongLong(0, nextID)); + set<size_t>::iterator itSet = examined.find(id); + while (itSet != examined.end() || data[id].m_bIsDead == true) + { + id = static_cast<size_t>(rnd.nextUniformLongLong(0, nextID)); + itSet = examined.find(id); + } + examined.insert(id); + + map<size_t, Region>::iterator itMap = data.find(id); + assert(itMap != data.end() && (*itMap).second.m_bIsDead == false); + + cout << T << " " << DELETE << " " << id << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << endl; + (*itMap).second.m_bIsDead = true; + + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(pair<size_t, Region>(nextID, r)); + + cout << T << " " << INSERT << " " << nextID << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << endl; + examined.insert(nextID); + nextID++; + } + + double stx = rnd.nextUniformDouble(); + double sty = rnd.nextUniformDouble(); + size_t qt = rnd.nextUniformLongLong(0, T); + cout << T << " " << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << " " << qt << " " << qt + 2<< endl; + stx = rnd.nextUniformDouble(); + sty = rnd.nextUniformDouble(); + qt = rnd.nextUniformLongLong(0, T); + cout << T << " " << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << " " << qt << " " << qt + 2<< endl; + stx = rnd.nextUniformDouble(); + sty = rnd.nextUniformDouble(); + qt = rnd.nextUniformLongLong(0, T); + cout << T << " " << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << " " << qt << " " << qt + 2<< endl; + } + + // delete everything at the end (for testing the special case when the tree dies out completely) + for (map<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + if (! it->second.m_bIsDead) + { + cout << 102 << " " << DELETE << " " << it->first << " " << it->second.m_xmin << " " << it->second.m_ymin << " " + << it->second.m_xmax << " " << it->second.m_ymax << endl; + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/MVRTreeLoad.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/MVRTreeLoad.cc new file mode 100644 index 000000000..7e07e2731 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/MVRTreeLoad.cc @@ -0,0 +1,209 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +// example of a Visitor pattern. +// see MVRTreeQuery for a more elaborate example. +class MyVisitor : public IVisitor +{ +public: + void visitNode(const INode& n) {} + + void visitData(const IData& d) + { + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 5) + { + cerr << "Usage: " << argv[0] << " input_file tree_file capacity query_type [intersection | 10NN]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[4], "intersection") == 0) queryType = 0; + else if (strcmp(argv[4], "10NN") == 0) queryType = 1; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file " << argv[1] << "." << endl; + return -1; + } + + // Create a new storage manager with the provided base name and a 4K page size. + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + //StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // Create a new, empty, MVRTree with dimensionality 2, minimum load 70%, using "file" as + // the StorageManager and the RSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = MVRTree::createNewMVRTree(*diskfile, 0.7, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::MVRTree::RV_RSTAR, indexIdentifier); + + size_t count = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2, t; + double plow[2], phigh[2]; + + while (fin) + { + fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + TimeRegion r = TimeRegion(plow, phigh, t, t, 2); + + //ostringstream os; + //os << r; + //string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see MVRTree::Node::load and MVRTree::Node::store for + // an example of how to do that). + + //tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + TimeRegion r = TimeRegion(plow, phigh, t, t, 2); + + if (tree->deleteData(r, id) == false) + { + cerr << "******ERROR******" << endl; + cerr << "Cannot delete id: " << id << " , count: " << count << endl; + return -1; + } + } + else if (op == QUERY) + { + size_t qt1, qt2; + fin >> qt1 >> qt2; + if (! fin.good()) continue; + + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + TimeRegion r = TimeRegion(plow, phigh, qt1, qt2, 2); + + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else + { + //Point p = Point(plow, 2); + //tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + cerr << "Operations: " << count << endl; + cerr << *tree; + //cerr << "Buffer hits: " << file->getHits() << endl; + cerr << "Index ID: " << indexIdentifier << endl; + + bool ret = tree->isIndexValid(); + if (ret == false) cerr << "ERROR: Structure is invalid!" << endl; + else cerr << "The stucture seems O.K." << endl; + + delete tree; + //delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/MVRTreeQuery.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/MVRTreeQuery.cc new file mode 100644 index 000000000..f8e367bc7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/MVRTreeQuery.cc @@ -0,0 +1,268 @@ +// Spatial Index Library +// +// Copyright (C) 2003 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +// example of a Visitor pattern. +// findes the index and leaf IO for answering the query and prints +// the resulting data IDs to stdout. +class MyVisitor : public IVisitor +{ +public: + size_t m_indexIO; + size_t m_leafIO; + +public: + MyVisitor() : m_indexIO(0), m_leafIO(0) {} + + void visitNode(const INode& n) + { + if (n.isLeaf()) m_leafIO++; + else m_indexIO++; + } + + void visitData(const IData& d) + { + //IShape* pS; + //d.getShape(&pS); + // do something. + //delete pS; + + // data should be an array of characters representing a Region as a string. + //byte* pData = 0; + //size_t cLen = 0; + //d.getData(cLen, &pData); + // do something. + //string s = reinterpret_cast<char*>(pData); + //cout << s << endl; + //delete[] pData; + + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +// example of a Strategy pattern. +// traverses the tree by level. +class MyQueryStrategy : public SpatialIndex::IQueryStrategy +{ +private: + queue<id_type> ids; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + IShape* ps; + entry.getShape(&ps); + Region* pr = dynamic_cast<Region*>(ps); + + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl << endl << endl; + // print node MBRs gnuplot style! + + delete ps; + + const INode* n = dynamic_cast<const INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 1) + { + for (size_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push(n->getChildIdentifier(cChild)); + } + } + + if (! ids.empty()) + { + nextEntry = ids.front(); ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } + } +}; + +// example of a Strategy pattern. +// find the total indexed space managed by the index (the MBR of the root). +class MyQueryStrategy2 : public IQueryStrategy +{ +public: + Region m_indexedSpace; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + // the first time we are called, entry points to the root. + + // stop after the root. + hasNext = false; + + IShape* ps; + entry.getShape(&ps); + ps->getMBR(m_indexedSpace); + delete ps; + } +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 4) + { + cerr << "Usage: " << argv[0] << " query_file tree_file query_type [intersection | 10NN]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[3], "intersection") == 0) queryType = 0; + else if (strcmp(argv[3], "10NN") == 0) queryType = 1; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open query file " << argv[1] << "." << endl; + return -1; + } + + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::loadDiskStorageManager(baseName); + // this will try to locate and open an already existing storage manager. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // If we need to open an existing tree stored in the storage manager, we only + // have to specify the index identifier as follows + ISpatialIndex* tree = MVRTree::loadMVRTree(*file, 1); + + size_t count = 0; + size_t indexIO = 0; + size_t leafIO = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2, t; + double plow[2], phigh[2]; + + while (fin) + { + fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == QUERY) + { + size_t qt1, qt2; + fin >> qt1 >> qt2; + if (! fin.good()) continue; + + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + TimeRegion r = TimeRegion(plow, phigh, qt1, qt2, 2); + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else + { + //Point p = Point(plow, 2); + //tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + + indexIO += vis.m_indexIO; + leafIO += vis.m_leafIO; + // example of the Visitor pattern usage, for calculating how many nodes + // were visited. + } + else + { + cerr << "This is not a query operation." << endl; + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + MyQueryStrategy2 qs; + tree->queryStrategy(qs); + + cerr << "Indexed space: " << qs.m_indexedSpace << endl; + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Index I/O: " << indexIO << endl; + cerr << "Leaf I/O: " << leafIO << endl; + cerr << "Buffer hits: " << file->getHits() << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail writting the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Makefile.am b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Makefile.am new file mode 100644 index 000000000..77a83a1e3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/Makefile.am @@ -0,0 +1,12 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_PROGRAMS = Generator Exhaustive MVRTreeLoad MVRTreeQuery +INCLUDES = -I../../include +Generator_SOURCES = Generator.cc +Generator_LDADD = ../../libspatialindex.la +Exhaustive_SOURCES = Exhaustive.cc +Exhaustive_LDADD = ../../libspatialindex.la +MVRTreeLoad_SOURCES = MVRTreeLoad.cc +MVRTreeLoad_LDADD = ../../libspatialindex.la +MVRTreeQuery_SOURCES = MVRTreeQuery.cc +MVRTreeQuery_LDADD = ../../libspatialindex.la + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/all-wcprops new file mode 100644 index 000000000..2c9e9f07b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/136/spatialindex/trunk/regressiontest/mvrtree/test1 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/mvrtree/test1/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/dir-prop-base new file mode 100644 index 000000000..3359090b2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 13 +data +queries + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/entries new file mode 100644 index 000000000..ef81df3eb --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/mvrtree/test1 +http://svn.gispython.org/spatialindex + + + +2009-08-19T15:24:15.611139Z +136 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.077108Z +6762ea822eddbf5712b4dd0420bf00ab +2007-08-01T20:37:49.786254Z +2 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +654 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/text-base/run.svn-base new file mode 100644 index 000000000..1aaa9c7f8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/.svn/text-base/run.svn-base @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator 1000 > d +awk '{if ($2 != 2) print $0}' < d > data +awk '{if ($2 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new MVR-Tree +../MVRTreeLoad data tree 20 intersection + +echo Querying MVR-Tree +../MVRTreeQuery queries tree intersection > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/run new file mode 100755 index 000000000..1aaa9c7f8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test1/run @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator 1000 > d +awk '{if ($2 != 2) print $0}' < d > data +awk '{if ($2 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new MVR-Tree +../MVRTreeLoad data tree 20 intersection + +echo Querying MVR-Tree +../MVRTreeQuery queries tree intersection > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/all-wcprops new file mode 100644 index 000000000..205654832 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/136/spatialindex/trunk/regressiontest/mvrtree/test2 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/mvrtree/test2/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/dir-prop-base new file mode 100644 index 000000000..4d3f4094b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 4 +mix + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/entries new file mode 100644 index 000000000..d10344f44 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/mvrtree/test2 +http://svn.gispython.org/spatialindex + + + +2009-08-19T15:24:15.611139Z +136 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.077108Z +3b371868b8e43606fa2a9044dea88d92 +2007-08-01T20:37:49.786254Z +2 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +484 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/text-base/run.svn-base new file mode 100644 index 000000000..de5cb8ba9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/.svn/text-base/run.svn-base @@ -0,0 +1,22 @@ +#! /bin/bash + +echo Generating dataset +../Generator 1000 > mix + +echo Creating new MVR-Tree and Querying +../MVRTreeLoad mix tree 20 intersection > res + +echo Running exhaustive search +../Exhaustive mix intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/run new file mode 100755 index 000000000..de5cb8ba9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/mvrtree/test2/run @@ -0,0 +1,22 @@ +#! /bin/bash + +echo Generating dataset +../Generator 1000 > mix + +echo Creating new MVR-Tree and Querying +../MVRTreeLoad mix tree 20 intersection > res + +echo Running exhaustive search +../Exhaustive mix intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/all-wcprops new file mode 100644 index 000000000..223a872a1 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/all-wcprops @@ -0,0 +1,71 @@ +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/182/spatialindex/trunk/regressiontest/rtree +END +RTreeBulkLoad.vcproj +K 25 +svn:wc:ra_dav:version-url +V 87 +/spatialindex/!svn/ver/113/spatialindex/trunk/regressiontest/rtree/RTreeBulkLoad.vcproj +END +RTreeBulkLoad.cc +K 25 +svn:wc:ra_dav:version-url +V 83 +/spatialindex/!svn/ver/130/spatialindex/trunk/regressiontest/rtree/RTreeBulkLoad.cc +END +RTreeLoad.vcproj +K 25 +svn:wc:ra_dav:version-url +V 83 +/spatialindex/!svn/ver/113/spatialindex/trunk/regressiontest/rtree/RTreeLoad.vcproj +END +RTreeLoad.cc +K 25 +svn:wc:ra_dav:version-url +V 78 +/spatialindex/!svn/ver/99/spatialindex/trunk/regressiontest/rtree/RTreeLoad.cc +END +Exhaustive.cc +K 25 +svn:wc:ra_dav:version-url +V 80 +/spatialindex/!svn/ver/182/spatialindex/trunk/regressiontest/rtree/Exhaustive.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/rtree/Makefile.am +END +RTreeExhaustive.vcproj +K 25 +svn:wc:ra_dav:version-url +V 89 +/spatialindex/!svn/ver/113/spatialindex/trunk/regressiontest/rtree/RTreeExhaustive.vcproj +END +RTreeQuery.vcproj +K 25 +svn:wc:ra_dav:version-url +V 84 +/spatialindex/!svn/ver/113/spatialindex/trunk/regressiontest/rtree/RTreeQuery.vcproj +END +Generator.cc +K 25 +svn:wc:ra_dav:version-url +V 79 +/spatialindex/!svn/ver/159/spatialindex/trunk/regressiontest/rtree/Generator.cc +END +RTreeGenerator.vcproj +K 25 +svn:wc:ra_dav:version-url +V 88 +/spatialindex/!svn/ver/113/spatialindex/trunk/regressiontest/rtree/RTreeGenerator.vcproj +END +RTreeQuery.cc +K 25 +svn:wc:ra_dav:version-url +V 80 +/spatialindex/!svn/ver/130/spatialindex/trunk/regressiontest/rtree/RTreeQuery.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/dir-prop-base new file mode 100644 index 000000000..7bb6f48a7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/dir-prop-base @@ -0,0 +1,16 @@ +K 10 +svn:ignore +V 102 +RTreeLoad +Makefile.in +Exhaustive +Generator +RTreeBulkLoad +.libs +RTreeQuery +.deps +Makefile +data +queries + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/entries new file mode 100644 index 000000000..291098630 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/entries @@ -0,0 +1,414 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/rtree +http://svn.gispython.org/spatialindex + + + +2010-04-12T17:17:47.459585Z +182 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +RTreeLoad.vcproj +file + + + + +2011-08-01T00:42:34.061219Z +e5a576790eb8a17371fe4d62be9509bb +2009-07-22T15:23:22.023161Z +113 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +7300 + +RTreeBulkLoad.cc +file + + + + +2011-08-01T00:42:34.061219Z +85ac7ce7d927d1ab1728b722f81f3f14 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +4240 + +RTreeExhaustive.vcproj +file + + + + +2011-08-01T00:42:34.065127Z +b6c4f117d41237d7994facd78cdb33e3 +2009-07-22T15:23:22.023161Z +113 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +7289 + +RTreeGenerator.vcproj +file + + + + +2011-08-01T00:42:34.069111Z +b986cef2bcefb6343a4566f2442fcd27 +2009-07-22T15:23:22.023161Z +113 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +7478 + +RTreeQuery.cc +file + + + + +2011-08-01T00:42:34.069111Z +6dc96f005443f88ef8087011d1aa9377 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +6704 + +test1 +dir + +RTreeBulkLoad.vcproj +file + + + + +2011-08-01T00:42:34.061219Z +7fa437b6694ddfea6d0c117dc4e76ac6 +2009-07-22T15:23:22.023161Z +113 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +7313 + +test2 +dir + +test3 +dir + +test4 +dir + +RTreeLoad.cc +file + + + + +2011-08-01T00:42:34.065127Z +ff1c54dece8ceec010ebd2ceeeebadd7 +2009-07-18T22:19:07.374702Z +99 +mhadji + + + + + + + + + + + + + + + + + + + + + +6476 + +RTreeQuery.vcproj +file + + + + +2011-08-01T00:42:34.069111Z +45626bc58899caae7830f30897d41237 +2009-07-22T15:23:22.023161Z +113 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +7303 + +Makefile.am +file + + + + +2011-08-01T00:42:34.065127Z +a5ed39045d9e34d87d9041738559ee68 +2007-08-01T20:37:49.786254Z +2 +hobu + + + + + + + + + + + + + + + + + + + + + +578 + +Exhaustive.cc +file + + + + +2011-08-01T00:42:34.065127Z +3cbcbf3303ed8e0bd3e816fcc40bd42e +2010-04-12T17:17:47.459585Z +182 +mhadji + + + + + + + + + + + + + + + + + + + + + +5133 + +Generator.cc +file + + + + +2011-08-01T00:42:34.069111Z +bdec99e2c151385e7bbb0c3b2dcb1da3 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +3854 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeBulkLoad.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeBulkLoad.vcproj.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeBulkLoad.vcproj.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeExhaustive.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeExhaustive.vcproj.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeExhaustive.vcproj.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeGenerator.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeGenerator.vcproj.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeGenerator.vcproj.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeLoad.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeLoad.vcproj.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeLoad.vcproj.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeQuery.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeQuery.vcproj.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/prop-base/RTreeQuery.vcproj.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Exhaustive.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Exhaustive.cc.svn-base new file mode 100644 index 000000000..62fc971ef --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Exhaustive.cc.svn-base @@ -0,0 +1,214 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <tools/Tools.h> +#include <cstring> +#include <cmath> + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + + // Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html + #pragma warning( disable: 4251 ) +#else + #include <stdint.h> +#endif + +class Region +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + + Region(double x1, double y1, double x2, double y2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + } + + bool intersects(Region& r) + { + if ( + m_xmin > r.m_xmax || m_xmax < r.m_xmin || + m_ymin > r.m_ymax || m_ymax < r.m_ymin) + return false; + + return true; + } + + double getMinDist(const Region& r) + { + double ret = 0.0; + + if (r.m_xmax < m_xmin) + ret += std::pow(m_xmin - r.m_xmax, 2.0); + else if (r.m_xmin > m_xmax) + ret += std::pow(r.m_xmin - m_xmax, 2.0); + + if (r.m_ymax < m_ymin) + ret += std::pow(m_ymin - r.m_ymax, 2.0); + else if (r.m_ymin > m_ymax) + ret += std::pow(r.m_ymin - m_ymax, 2.0); + + return ret; + } +}; + +class NNEntry +{ +public: + size_t m_id; + double m_dist; + + NNEntry(size_t id, double dist) : m_id(id), m_dist(dist) {} + + struct greater : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_dist > __y->m_dist; } + }; +}; + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " data_file query_type [intersection | 10NN | selfjoin]." << std::endl; + return -1; + } + uint32_t queryType = 0; + + if (strcmp(argv[2], "intersection") == 0) queryType = 0; + else if (strcmp(argv[2], "10NN") == 0) queryType = 1; + else if (strcmp(argv[2], "selfjoin") == 0) queryType = 2; + else + { + std::cerr << "Unknown query type." << std::endl; + return -1; + } + + std::ifstream fin(argv[1]); + if (! fin) + { + std::cerr << "Cannot open data file" << argv[1] << "." << std::endl; + return -1; + } + + std::multimap<size_t, Region> data; + size_t id; + uint32_t op; + double x1, x2, y1, y2; + + while (fin) + { + fin >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; + + if (op == INSERT) + { + //insert + data.insert(std::pair<size_t, Region>(id, Region(x1, y1, x2, y2))); + } + else if (op == DELETE) + { + data.erase(id); + } + else if (op == QUERY) + { + //query + if (queryType == 0) + { + Region query = Region(x1, y1, x2, y2); + for (std::multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + if (query.intersects((*it).second)) std::cout << (*it).first << std::endl; + } + } + else if (queryType == 1) + { + Region query = Region(x1, y1, x1, y1); + + std::priority_queue<NNEntry*, std::vector<NNEntry*>, NNEntry::greater > queue; + + for (std::multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + queue.push(new NNEntry((*it).first, (*it).second.getMinDist(query))); + } + + size_t count = 0; + double knearest = 0.0; + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + + if (count >= 10 && e->m_dist > knearest) break; + + //std::cout << e->m_id << " " << e->m_dist << std::endl; + std::cout << e->m_id << std::endl; + count++; + knearest = e->m_dist; + delete e; + } + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + delete e; + } + } + else + { + Region query = Region(x1, y1, x2, y2); + + for (std::multimap<size_t, Region>::iterator it1 = data.begin(); it1 != data.end(); it1++) + { + if (query.intersects((*it1).second)) + { + for (std::multimap<size_t, Region>::iterator it2 = data.begin(); it2 != data.end(); it2++) + { + if ( + (*it1).first != (*it2).first && + query.intersects((*it2).second) && + (*it1).second.intersects((*it2).second)) + { + std::cout << (*it1).first << " " << (*it2).first << std::endl; + } + } + } + } + } + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Generator.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Generator.cc.svn-base new file mode 100644 index 000000000..41f696811 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Generator.cc.svn-base @@ -0,0 +1,128 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <tools/Tools.h> +#include <cmath> +#include <limits> + +#include <set> + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +class Region +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + + Region(double x1, double y1, double x2, double y2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + } +}; + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " number_of_data time_instants." << std::endl; + return -1; + } + + size_t simulationLength = atol(argv[2]); + size_t numberOfObjects = atol(argv[1]); + std::map<size_t, Region> data; + Tools::Random rnd; + + for (size_t i = 0; i < numberOfObjects; i++) + { + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(std::pair<size_t, Region>(i, r)); + + std::cout << INSERT << " " << i << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << std::endl; + } + + if (simulationLength == 0) + { + for (size_t i = 0; i < 10; i++) + { + double stx = rnd.nextUniformDouble(); + double sty = rnd.nextUniformDouble(); + std::cout << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << std::endl; + } + } + + size_t A = static_cast<size_t>(std::floor(static_cast<double>(numberOfObjects) * 0.05)); + + for (size_t T = 1; T <= simulationLength; T++) + { + std::cerr << (simulationLength + 1 - T) << std::endl; + std::set<size_t> examined; + + for (size_t a = 0; a < A; a++) + { + // find an id that is not yet examined. + size_t id = static_cast<size_t>(rnd.nextUniformLong(0, numberOfObjects)); + std::set<size_t>::iterator itSet = examined.find(id); + + while (itSet != examined.end()) + { + id = static_cast<size_t>(rnd.nextUniformLong(0, numberOfObjects)); + itSet = examined.find(id); + } + examined.insert(id); + + std::map<size_t, Region>::iterator itMap = data.find(id); + assert(itMap != data.end()); + + std::cout << DELETE << " " << id << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << std::endl; + + double x = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + (*itMap).second.m_xmin = x; + (*itMap).second.m_xmax = x + dx; + double y = rnd.nextUniformDouble(); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + (*itMap).second.m_ymin = y; + (*itMap).second.m_ymax = y + dy; + + std::cout << INSERT << " " << id << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << std::endl; + } + + double stx = rnd.nextUniformDouble(); + double sty = rnd.nextUniformDouble(); + std::cout << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << std::endl; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..820f9dd07 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,13 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_PROGRAMS = Generator Exhaustive RTreeLoad RTreeQuery RTreeBulkLoad +INCLUDES = -I../../include +Generator_SOURCES = Generator.cc +Generator_LDADD = ../../libspatialindex.la +Exhaustive_SOURCES = Exhaustive.cc +Exhaustive_LDADD = ../../libspatialindex.la +RTreeLoad_SOURCES = RTreeLoad.cc +RTreeLoad_LDADD = ../../libspatialindex.la +RTreeQuery_SOURCES = RTreeQuery.cc +RTreeQuery_LDADD = ../../libspatialindex.la +RTreeBulkLoad_SOURCES = RTreeBulkLoad.cc +RTreeBulkLoad_LDADD = ../../libspatialindex.la diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeBulkLoad.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeBulkLoad.cc.svn-base new file mode 100644 index 000000000..0726d3d08 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeBulkLoad.cc.svn-base @@ -0,0 +1,162 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +class MyDataStream : public IDataStream +{ +public: + MyDataStream(std::string inputFile) : m_pNext(0) + { + m_fin.open(inputFile.c_str()); + + if (! m_fin) + throw Tools::IllegalArgumentException("Input file not found."); + + readNextEntry(); + } + + virtual ~MyDataStream() + { + if (m_pNext != 0) delete m_pNext; + } + + virtual IData* getNext() + { + if (m_pNext == 0) return 0; + + RTree::Data* ret = m_pNext; + m_pNext = 0; + readNextEntry(); + return ret; + } + + virtual bool hasNext() + { + return (m_pNext != 0); + } + + virtual uint32_t size() + { + throw Tools::NotSupportedException("Operation not supported."); + } + + virtual void rewind() + { + if (m_pNext != 0) + { + delete m_pNext; + m_pNext = 0; + } + + m_fin.seekg(0, std::ios::beg); + readNextEntry(); + } + + void readNextEntry() + { + id_type id; + uint32_t op; + double low[2], high[2]; + + m_fin >> op >> id >> low[0] >> low[1] >> high[0] >> high[1]; + + if (m_fin.good()) + { + if (op != INSERT) + throw Tools::IllegalArgumentException( + "The data input should contain insertions only." + ); + + Region r(low, high, 2); + m_pNext = new RTree::Data(sizeof(double), reinterpret_cast<byte*>(low), r, id); + // Associate a bogus data array with every entry for testing purposes. + // Once the data array is given to RTRee:Data a local copy will be created. + // Hence, the input data array can be deleted after this operation if not + // needed anymore. + } + } + + std::ifstream m_fin; + RTree::Data* m_pNext; +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] << " input_file tree_file capacity utilization." << std::endl; + return -1; + } + + std::string baseName = argv[2]; + double utilization = atof(argv[4]); + + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + // Create a new storage manager with the provided base name and a 4K page size. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + MyDataStream stream(argv[1]); + + // Create and bulk load a new RTree with dimensionality 2, using "file" as + // the StorageManager and the RSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = RTree::createAndBulkLoadNewRTree( + RTree::BLM_STR, stream, *file, utilization, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::RTree::RV_RSTAR, indexIdentifier); + + std::cerr << *tree; + std::cerr << "Buffer hits: " << file->getHits() << std::endl; + std::cerr << "Index ID: " << indexIdentifier << std::endl; + + bool ret = tree->isIndexValid(); + if (ret == false) std::cerr << "ERROR: Structure is invalid!" << std::endl; + else std::cerr << "The stucture seems O.K." << std::endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + std::cerr << "******ERROR******" << std::endl; + std::string s = e.what(); + std::cerr << s << std::endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeBulkLoad.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeBulkLoad.vcproj.svn-base new file mode 100644 index 000000000..3e8526057 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeBulkLoad.vcproj.svn-base @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeBulkLoad"
+ ProjectGUID="{7D9C8655-0155-4EE3-B04C-6D831E2982CE}"
+ RootNamespace="regressiontest"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\RTreeBulkLoad.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeExhaustive.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeExhaustive.vcproj.svn-base new file mode 100644 index 000000000..208fa4e5f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeExhaustive.vcproj.svn-base @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeExhaustive"
+ ProjectGUID="{D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}"
+ RootNamespace="RTreeExhaustive"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Exhaustive.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeGenerator.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeGenerator.vcproj.svn-base new file mode 100644 index 000000000..b0585e096 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeGenerator.vcproj.svn-base @@ -0,0 +1,364 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeGenerator"
+ ProjectGUID="{03504DB7-ACF3-40CF-A8A7-310E80666DC0}"
+ RootNamespace="RTreeGenerator"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Generator.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeLoad.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeLoad.cc.svn-base new file mode 100644 index 000000000..4b0b97bc3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeLoad.cc.svn-base @@ -0,0 +1,202 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// see RTreeQuery for a more elaborate example. +class MyVisitor : public IVisitor +{ +public: + void visitNode(const INode& n) {} + + void visitData(const IData& d) + { + std::cout << d.getIdentifier() << std::endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] << " input_file tree_file capacity query_type [intersection | 10NN | selfjoin]." << std::endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[4], "intersection") == 0) queryType = 0; + else if (strcmp(argv[4], "10NN") == 0) queryType = 1; + else if (strcmp(argv[4], "selfjoin") == 0) queryType = 2; + else + { + std::cerr << "Unknown query type." << std::endl; + return -1; + } + + std::ifstream fin(argv[1]); + if (! fin) + { + std::cerr << "Cannot open data file " << argv[1] << "." << std::endl; + return -1; + } + + // Create a new storage manager with the provided base name and a 4K page size. + std::string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // Create a new, empty, RTree with dimensionality 2, minimum load 70%, using "file" as + // the StorageManager and the RSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = RTree::createNewRTree(*file, 0.7, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::RTree::RV_RSTAR, indexIdentifier); + + size_t count = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2; + double plow[2], phigh[2]; + + while (fin) + { + fin >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + Region r = Region(plow, phigh, 2); + + std::ostringstream os; + os << r; + std::string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see RTree::Node::load and RTree::Node::store for + // an example of how to do that). + + tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + //tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + Region r = Region(plow, phigh, 2); + + if (tree->deleteData(r, id) == false) + { + std::cerr << "******ERROR******" << std::endl; + std::cerr << "Cannot delete id: " << id << " , count: " << count << std::endl; + return -1; + } + } + else if (op == QUERY) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + Region r = Region(plow, phigh, 2); + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else if (queryType == 1) + { + Point p = Point(plow, 2); + tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + else + { + Region r = Region(plow, phigh, 2); + tree->selfJoinQuery(r, vis); + } + } + + if ((count % 1000) == 0) + std::cerr << count << std::endl; + + count++; + } + + std::cerr << "Operations: " << count << std::endl; + std::cerr << *tree; + std::cerr << "Buffer hits: " << file->getHits() << std::endl; + std::cerr << "Index ID: " << indexIdentifier << std::endl; + + bool ret = tree->isIndexValid(); + if (ret == false) std::cerr << "ERROR: Structure is invalid!" << std::endl; + else std::cerr << "The stucture seems O.K." << std::endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + std::cerr << "******ERROR******" << std::endl; + std::string s = e.what(); + std::cerr << s << std::endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeLoad.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeLoad.vcproj.svn-base new file mode 100644 index 000000000..e91e5e64a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeLoad.vcproj.svn-base @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeLoad"
+ ProjectGUID="{551D683C-E5DC-4713-9D9F-F629D15BE5DA}"
+ RootNamespace="RTreeLoad"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\RTreeLoad.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeQuery.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeQuery.cc.svn-base new file mode 100644 index 000000000..865054ebe --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeQuery.cc.svn-base @@ -0,0 +1,272 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// findes the index and leaf IO for answering the query and prints +// the resulting data IDs to stdout. +class MyVisitor : public IVisitor +{ +public: + size_t m_indexIO; + size_t m_leafIO; + +public: + MyVisitor() : m_indexIO(0), m_leafIO(0) {} + + void visitNode(const INode& n) + { + if (n.isLeaf()) m_leafIO++; + else m_indexIO++; + } + + void visitData(const IData& d) + { + IShape* pS; + d.getShape(&pS); + // do something. + delete pS; + + // data should be an array of characters representing a Region as a string. + byte* pData = 0; + uint32_t cLen = 0; + d.getData(cLen, &pData); + // do something. + //string s = reinterpret_cast<char*>(pData); + //cout << s << endl; + delete[] pData; + + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) + { + cout << v[0]->getIdentifier() << " " << v[1]->getIdentifier() << endl; + } +}; + +// example of a Strategy pattern. +// traverses the tree by level. +class MyQueryStrategy : public SpatialIndex::IQueryStrategy +{ +private: + queue<id_type> ids; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + IShape* ps; + entry.getShape(&ps); + Region* pr = dynamic_cast<Region*>(ps); + + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl << endl << endl; + // print node MBRs gnuplot style! + + delete ps; + + const INode* n = dynamic_cast<const INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 1) + { + for (uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push(n->getChildIdentifier(cChild)); + } + } + + if (! ids.empty()) + { + nextEntry = ids.front(); ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } + } +}; + +// example of a Strategy pattern. +// find the total indexed space managed by the index (the MBR of the root). +class MyQueryStrategy2 : public IQueryStrategy +{ +public: + Region m_indexedSpace; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + // the first time we are called, entry points to the root. + + // stop after the root. + hasNext = false; + + IShape* ps; + entry.getShape(&ps); + ps->getMBR(m_indexedSpace); + delete ps; + } +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 4) + { + cerr << "Usage: " << argv[0] << " query_file tree_file query_type [intersection | 10NN | selfjoin]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[3], "intersection") == 0) queryType = 0; + else if (strcmp(argv[3], "10NN") == 0) queryType = 1; + else if (strcmp(argv[3], "selfjoin") == 0) queryType = 2; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open query file " << argv[1] << "." << endl; + return -1; + } + + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::loadDiskStorageManager(baseName); + // this will try to locate and open an already existing storage manager. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // If we need to open an existing tree stored in the storage manager, we only + // have to specify the index identifier as follows + ISpatialIndex* tree = RTree::loadRTree(*file, 1); + + size_t count = 0; + size_t indexIO = 0; + size_t leafIO = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2; + double plow[2], phigh[2]; + + while (fin) + { + fin >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == QUERY) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + Region r = Region(plow, phigh, 2); + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else if (queryType == 1) + { + Point p = Point(plow, 2); + tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + else + { + Region r = Region(plow, phigh, 2); + tree->selfJoinQuery(r, vis); + } + + indexIO += vis.m_indexIO; + leafIO += vis.m_leafIO; + // example of the Visitor pattern usage, for calculating how many nodes + // were visited. + } + else + { + cerr << "This is not a query operation." << endl; + } + + if ((count % 1000) == 0) cerr << count << endl; + + count++; + } + + MyQueryStrategy2 qs; + tree->queryStrategy(qs); + + cerr << "Indexed space: " << qs.m_indexedSpace << endl; + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Index I/O: " << indexIO << endl; + cerr << "Leaf I/O: " << leafIO << endl; + cerr << "Buffer hits: " << file->getHits() << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail writting the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeQuery.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeQuery.vcproj.svn-base new file mode 100644 index 000000000..c5fe4b981 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/.svn/text-base/RTreeQuery.vcproj.svn-base @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeQuery"
+ ProjectGUID="{1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}"
+ RootNamespace="RTreeQuery"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\RTreeQuery.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Exhaustive.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Exhaustive.cc new file mode 100644 index 000000000..62fc971ef --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Exhaustive.cc @@ -0,0 +1,214 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <tools/Tools.h> +#include <cstring> +#include <cmath> + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + + // Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html + #pragma warning( disable: 4251 ) +#else + #include <stdint.h> +#endif + +class Region +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + + Region(double x1, double y1, double x2, double y2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + } + + bool intersects(Region& r) + { + if ( + m_xmin > r.m_xmax || m_xmax < r.m_xmin || + m_ymin > r.m_ymax || m_ymax < r.m_ymin) + return false; + + return true; + } + + double getMinDist(const Region& r) + { + double ret = 0.0; + + if (r.m_xmax < m_xmin) + ret += std::pow(m_xmin - r.m_xmax, 2.0); + else if (r.m_xmin > m_xmax) + ret += std::pow(r.m_xmin - m_xmax, 2.0); + + if (r.m_ymax < m_ymin) + ret += std::pow(m_ymin - r.m_ymax, 2.0); + else if (r.m_ymin > m_ymax) + ret += std::pow(r.m_ymin - m_ymax, 2.0); + + return ret; + } +}; + +class NNEntry +{ +public: + size_t m_id; + double m_dist; + + NNEntry(size_t id, double dist) : m_id(id), m_dist(dist) {} + + struct greater : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_dist > __y->m_dist; } + }; +}; + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " data_file query_type [intersection | 10NN | selfjoin]." << std::endl; + return -1; + } + uint32_t queryType = 0; + + if (strcmp(argv[2], "intersection") == 0) queryType = 0; + else if (strcmp(argv[2], "10NN") == 0) queryType = 1; + else if (strcmp(argv[2], "selfjoin") == 0) queryType = 2; + else + { + std::cerr << "Unknown query type." << std::endl; + return -1; + } + + std::ifstream fin(argv[1]); + if (! fin) + { + std::cerr << "Cannot open data file" << argv[1] << "." << std::endl; + return -1; + } + + std::multimap<size_t, Region> data; + size_t id; + uint32_t op; + double x1, x2, y1, y2; + + while (fin) + { + fin >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; + + if (op == INSERT) + { + //insert + data.insert(std::pair<size_t, Region>(id, Region(x1, y1, x2, y2))); + } + else if (op == DELETE) + { + data.erase(id); + } + else if (op == QUERY) + { + //query + if (queryType == 0) + { + Region query = Region(x1, y1, x2, y2); + for (std::multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + if (query.intersects((*it).second)) std::cout << (*it).first << std::endl; + } + } + else if (queryType == 1) + { + Region query = Region(x1, y1, x1, y1); + + std::priority_queue<NNEntry*, std::vector<NNEntry*>, NNEntry::greater > queue; + + for (std::multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++) + { + queue.push(new NNEntry((*it).first, (*it).second.getMinDist(query))); + } + + size_t count = 0; + double knearest = 0.0; + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + + if (count >= 10 && e->m_dist > knearest) break; + + //std::cout << e->m_id << " " << e->m_dist << std::endl; + std::cout << e->m_id << std::endl; + count++; + knearest = e->m_dist; + delete e; + } + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + delete e; + } + } + else + { + Region query = Region(x1, y1, x2, y2); + + for (std::multimap<size_t, Region>::iterator it1 = data.begin(); it1 != data.end(); it1++) + { + if (query.intersects((*it1).second)) + { + for (std::multimap<size_t, Region>::iterator it2 = data.begin(); it2 != data.end(); it2++) + { + if ( + (*it1).first != (*it2).first && + query.intersects((*it2).second) && + (*it1).second.intersects((*it2).second)) + { + std::cout << (*it1).first << " " << (*it2).first << std::endl; + } + } + } + } + } + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Generator.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Generator.cc new file mode 100644 index 000000000..41f696811 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Generator.cc @@ -0,0 +1,128 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <tools/Tools.h> +#include <cmath> +#include <limits> + +#include <set> + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +class Region +{ +public: + double m_xmin, m_ymin, m_xmax, m_ymax; + + Region(double x1, double y1, double x2, double y2) + { + m_xmin = (x1 < x2) ? x1 : x2; + m_ymin = (y1 < y2) ? y1 : y2; + m_xmax = (x1 > x2) ? x1 : x2; + m_ymax = (y1 > y2) ? y1 : y2; + } +}; + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " number_of_data time_instants." << std::endl; + return -1; + } + + size_t simulationLength = atol(argv[2]); + size_t numberOfObjects = atol(argv[1]); + std::map<size_t, Region> data; + Tools::Random rnd; + + for (size_t i = 0; i < numberOfObjects; i++) + { + double x = rnd.nextUniformDouble(); + double y = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + Region r = Region(x, y, x + dx, y + dy); + + data.insert(std::pair<size_t, Region>(i, r)); + + std::cout << INSERT << " " << i << " " << r.m_xmin << " " << r.m_ymin << " " + << r.m_xmax << " " << r.m_ymax << std::endl; + } + + if (simulationLength == 0) + { + for (size_t i = 0; i < 10; i++) + { + double stx = rnd.nextUniformDouble(); + double sty = rnd.nextUniformDouble(); + std::cout << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << std::endl; + } + } + + size_t A = static_cast<size_t>(std::floor(static_cast<double>(numberOfObjects) * 0.05)); + + for (size_t T = 1; T <= simulationLength; T++) + { + std::cerr << (simulationLength + 1 - T) << std::endl; + std::set<size_t> examined; + + for (size_t a = 0; a < A; a++) + { + // find an id that is not yet examined. + size_t id = static_cast<size_t>(rnd.nextUniformLong(0, numberOfObjects)); + std::set<size_t>::iterator itSet = examined.find(id); + + while (itSet != examined.end()) + { + id = static_cast<size_t>(rnd.nextUniformLong(0, numberOfObjects)); + itSet = examined.find(id); + } + examined.insert(id); + + std::map<size_t, Region>::iterator itMap = data.find(id); + assert(itMap != data.end()); + + std::cout << DELETE << " " << id << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << std::endl; + + double x = rnd.nextUniformDouble(); + double dx = rnd.nextUniformDouble(0.0001, 0.1); + (*itMap).second.m_xmin = x; + (*itMap).second.m_xmax = x + dx; + double y = rnd.nextUniformDouble(); + double dy = rnd.nextUniformDouble(0.0001, 0.1); + (*itMap).second.m_ymin = y; + (*itMap).second.m_ymax = y + dy; + + std::cout << INSERT << " " << id << " " << (*itMap).second.m_xmin << " " << (*itMap).second.m_ymin << " " + << (*itMap).second.m_xmax << " " << (*itMap).second.m_ymax << std::endl; + } + + double stx = rnd.nextUniformDouble(); + double sty = rnd.nextUniformDouble(); + std::cout << QUERY << " 9999999 " << stx << " " << sty << " " << (stx + 0.01) << " " << (sty + 0.01) << std::endl; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Makefile.am b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Makefile.am new file mode 100644 index 000000000..820f9dd07 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/Makefile.am @@ -0,0 +1,13 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_PROGRAMS = Generator Exhaustive RTreeLoad RTreeQuery RTreeBulkLoad +INCLUDES = -I../../include +Generator_SOURCES = Generator.cc +Generator_LDADD = ../../libspatialindex.la +Exhaustive_SOURCES = Exhaustive.cc +Exhaustive_LDADD = ../../libspatialindex.la +RTreeLoad_SOURCES = RTreeLoad.cc +RTreeLoad_LDADD = ../../libspatialindex.la +RTreeQuery_SOURCES = RTreeQuery.cc +RTreeQuery_LDADD = ../../libspatialindex.la +RTreeBulkLoad_SOURCES = RTreeBulkLoad.cc +RTreeBulkLoad_LDADD = ../../libspatialindex.la diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeBulkLoad.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeBulkLoad.cc new file mode 100644 index 000000000..0726d3d08 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeBulkLoad.cc @@ -0,0 +1,162 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +class MyDataStream : public IDataStream +{ +public: + MyDataStream(std::string inputFile) : m_pNext(0) + { + m_fin.open(inputFile.c_str()); + + if (! m_fin) + throw Tools::IllegalArgumentException("Input file not found."); + + readNextEntry(); + } + + virtual ~MyDataStream() + { + if (m_pNext != 0) delete m_pNext; + } + + virtual IData* getNext() + { + if (m_pNext == 0) return 0; + + RTree::Data* ret = m_pNext; + m_pNext = 0; + readNextEntry(); + return ret; + } + + virtual bool hasNext() + { + return (m_pNext != 0); + } + + virtual uint32_t size() + { + throw Tools::NotSupportedException("Operation not supported."); + } + + virtual void rewind() + { + if (m_pNext != 0) + { + delete m_pNext; + m_pNext = 0; + } + + m_fin.seekg(0, std::ios::beg); + readNextEntry(); + } + + void readNextEntry() + { + id_type id; + uint32_t op; + double low[2], high[2]; + + m_fin >> op >> id >> low[0] >> low[1] >> high[0] >> high[1]; + + if (m_fin.good()) + { + if (op != INSERT) + throw Tools::IllegalArgumentException( + "The data input should contain insertions only." + ); + + Region r(low, high, 2); + m_pNext = new RTree::Data(sizeof(double), reinterpret_cast<byte*>(low), r, id); + // Associate a bogus data array with every entry for testing purposes. + // Once the data array is given to RTRee:Data a local copy will be created. + // Hence, the input data array can be deleted after this operation if not + // needed anymore. + } + } + + std::ifstream m_fin; + RTree::Data* m_pNext; +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] << " input_file tree_file capacity utilization." << std::endl; + return -1; + } + + std::string baseName = argv[2]; + double utilization = atof(argv[4]); + + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + // Create a new storage manager with the provided base name and a 4K page size. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + MyDataStream stream(argv[1]); + + // Create and bulk load a new RTree with dimensionality 2, using "file" as + // the StorageManager and the RSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = RTree::createAndBulkLoadNewRTree( + RTree::BLM_STR, stream, *file, utilization, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::RTree::RV_RSTAR, indexIdentifier); + + std::cerr << *tree; + std::cerr << "Buffer hits: " << file->getHits() << std::endl; + std::cerr << "Index ID: " << indexIdentifier << std::endl; + + bool ret = tree->isIndexValid(); + if (ret == false) std::cerr << "ERROR: Structure is invalid!" << std::endl; + else std::cerr << "The stucture seems O.K." << std::endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + std::cerr << "******ERROR******" << std::endl; + std::string s = e.what(); + std::cerr << s << std::endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeBulkLoad.vcproj b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeBulkLoad.vcproj new file mode 100755 index 000000000..3e8526057 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeBulkLoad.vcproj @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeBulkLoad"
+ ProjectGUID="{7D9C8655-0155-4EE3-B04C-6D831E2982CE}"
+ RootNamespace="regressiontest"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\RTreeBulkLoad.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeExhaustive.vcproj b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeExhaustive.vcproj new file mode 100755 index 000000000..208fa4e5f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeExhaustive.vcproj @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeExhaustive"
+ ProjectGUID="{D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}"
+ RootNamespace="RTreeExhaustive"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\Exhaustive.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Exhaustive.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeGenerator.vcproj b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeGenerator.vcproj new file mode 100755 index 000000000..b0585e096 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeGenerator.vcproj @@ -0,0 +1,364 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeGenerator"
+ ProjectGUID="{03504DB7-ACF3-40CF-A8A7-310E80666DC0}"
+ RootNamespace="RTreeGenerator"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ OutputFile="$(OutDir)\Generator.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Generator.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeLoad.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeLoad.cc new file mode 100644 index 000000000..4b0b97bc3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeLoad.cc @@ -0,0 +1,202 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// see RTreeQuery for a more elaborate example. +class MyVisitor : public IVisitor +{ +public: + void visitNode(const INode& n) {} + + void visitData(const IData& d) + { + std::cout << d.getIdentifier() << std::endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] << " input_file tree_file capacity query_type [intersection | 10NN | selfjoin]." << std::endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[4], "intersection") == 0) queryType = 0; + else if (strcmp(argv[4], "10NN") == 0) queryType = 1; + else if (strcmp(argv[4], "selfjoin") == 0) queryType = 2; + else + { + std::cerr << "Unknown query type." << std::endl; + return -1; + } + + std::ifstream fin(argv[1]); + if (! fin) + { + std::cerr << "Cannot open data file " << argv[1] << "." << std::endl; + return -1; + } + + // Create a new storage manager with the provided base name and a 4K page size. + std::string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // Create a new, empty, RTree with dimensionality 2, minimum load 70%, using "file" as + // the StorageManager and the RSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = RTree::createNewRTree(*file, 0.7, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::RTree::RV_RSTAR, indexIdentifier); + + size_t count = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2; + double plow[2], phigh[2]; + + while (fin) + { + fin >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + Region r = Region(plow, phigh, 2); + + std::ostringstream os; + os << r; + std::string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see RTree::Node::load and RTree::Node::store for + // an example of how to do that). + + tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + //tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + Region r = Region(plow, phigh, 2); + + if (tree->deleteData(r, id) == false) + { + std::cerr << "******ERROR******" << std::endl; + std::cerr << "Cannot delete id: " << id << " , count: " << count << std::endl; + return -1; + } + } + else if (op == QUERY) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + Region r = Region(plow, phigh, 2); + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else if (queryType == 1) + { + Point p = Point(plow, 2); + tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + else + { + Region r = Region(plow, phigh, 2); + tree->selfJoinQuery(r, vis); + } + } + + if ((count % 1000) == 0) + std::cerr << count << std::endl; + + count++; + } + + std::cerr << "Operations: " << count << std::endl; + std::cerr << *tree; + std::cerr << "Buffer hits: " << file->getHits() << std::endl; + std::cerr << "Index ID: " << indexIdentifier << std::endl; + + bool ret = tree->isIndexValid(); + if (ret == false) std::cerr << "ERROR: Structure is invalid!" << std::endl; + else std::cerr << "The stucture seems O.K." << std::endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + std::cerr << "******ERROR******" << std::endl; + std::string s = e.what(); + std::cerr << s << std::endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeLoad.vcproj b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeLoad.vcproj new file mode 100755 index 000000000..e91e5e64a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeLoad.vcproj @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeLoad"
+ ProjectGUID="{551D683C-E5DC-4713-9D9F-F629D15BE5DA}"
+ RootNamespace="RTreeLoad"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\RTreeLoad.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeQuery.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeQuery.cc new file mode 100644 index 000000000..865054ebe --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeQuery.cc @@ -0,0 +1,272 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +#include <cstring> + +// include library header file. +#include <SpatialIndex.h> + +using namespace SpatialIndex; +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// findes the index and leaf IO for answering the query and prints +// the resulting data IDs to stdout. +class MyVisitor : public IVisitor +{ +public: + size_t m_indexIO; + size_t m_leafIO; + +public: + MyVisitor() : m_indexIO(0), m_leafIO(0) {} + + void visitNode(const INode& n) + { + if (n.isLeaf()) m_leafIO++; + else m_indexIO++; + } + + void visitData(const IData& d) + { + IShape* pS; + d.getShape(&pS); + // do something. + delete pS; + + // data should be an array of characters representing a Region as a string. + byte* pData = 0; + uint32_t cLen = 0; + d.getData(cLen, &pData); + // do something. + //string s = reinterpret_cast<char*>(pData); + //cout << s << endl; + delete[] pData; + + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) + { + cout << v[0]->getIdentifier() << " " << v[1]->getIdentifier() << endl; + } +}; + +// example of a Strategy pattern. +// traverses the tree by level. +class MyQueryStrategy : public SpatialIndex::IQueryStrategy +{ +private: + queue<id_type> ids; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + IShape* ps; + entry.getShape(&ps); + Region* pr = dynamic_cast<Region*>(ps); + + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl << endl << endl; + // print node MBRs gnuplot style! + + delete ps; + + const INode* n = dynamic_cast<const INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 1) + { + for (uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push(n->getChildIdentifier(cChild)); + } + } + + if (! ids.empty()) + { + nextEntry = ids.front(); ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } + } +}; + +// example of a Strategy pattern. +// find the total indexed space managed by the index (the MBR of the root). +class MyQueryStrategy2 : public IQueryStrategy +{ +public: + Region m_indexedSpace; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + // the first time we are called, entry points to the root. + + // stop after the root. + hasNext = false; + + IShape* ps; + entry.getShape(&ps); + ps->getMBR(m_indexedSpace); + delete ps; + } +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 4) + { + cerr << "Usage: " << argv[0] << " query_file tree_file query_type [intersection | 10NN | selfjoin]." << endl; + return -1; + } + + uint32_t queryType = 0; + + if (strcmp(argv[3], "intersection") == 0) queryType = 0; + else if (strcmp(argv[3], "10NN") == 0) queryType = 1; + else if (strcmp(argv[3], "selfjoin") == 0) queryType = 2; + else + { + cerr << "Unknown query type." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open query file " << argv[1] << "." << endl; + return -1; + } + + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::loadDiskStorageManager(baseName); + // this will try to locate and open an already existing storage manager. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // If we need to open an existing tree stored in the storage manager, we only + // have to specify the index identifier as follows + ISpatialIndex* tree = RTree::loadRTree(*file, 1); + + size_t count = 0; + size_t indexIO = 0; + size_t leafIO = 0; + id_type id; + uint32_t op; + double x1, x2, y1, y2; + double plow[2], phigh[2]; + + while (fin) + { + fin >> op >> id >> x1 >> y1 >> x2 >> y2; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == QUERY) + { + plow[0] = x1; plow[1] = y1; + phigh[0] = x2; phigh[1] = y2; + + MyVisitor vis; + + if (queryType == 0) + { + Region r = Region(plow, phigh, 2); + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + else if (queryType == 1) + { + Point p = Point(plow, 2); + tree->nearestNeighborQuery(10, p, vis); + // this will find the 10 nearest neighbors. + } + else + { + Region r = Region(plow, phigh, 2); + tree->selfJoinQuery(r, vis); + } + + indexIO += vis.m_indexIO; + leafIO += vis.m_leafIO; + // example of the Visitor pattern usage, for calculating how many nodes + // were visited. + } + else + { + cerr << "This is not a query operation." << endl; + } + + if ((count % 1000) == 0) cerr << count << endl; + + count++; + } + + MyQueryStrategy2 qs; + tree->queryStrategy(qs); + + cerr << "Indexed space: " << qs.m_indexedSpace << endl; + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Index I/O: " << indexIO << endl; + cerr << "Leaf I/O: " << leafIO << endl; + cerr << "Buffer hits: " << file->getHits() << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail writting the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeQuery.vcproj b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeQuery.vcproj new file mode 100755 index 000000000..c5fe4b981 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/RTreeQuery.vcproj @@ -0,0 +1,360 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="RTreeQuery"
+ ProjectGUID="{1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}"
+ RootNamespace="RTreeQuery"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64_d.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="."
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="spatialindex64.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../.."
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\RTreeQuery.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/all-wcprops new file mode 100644 index 000000000..6b4b31fb5 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/136/spatialindex/trunk/regressiontest/rtree/test1 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/130/spatialindex/trunk/regressiontest/rtree/test1/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/dir-prop-base new file mode 100644 index 000000000..3359090b2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 13 +data +queries + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/entries new file mode 100644 index 000000000..e4258db19 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/rtree/test1 +http://svn.gispython.org/spatialindex + + + +2009-08-19T15:24:15.611139Z +136 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:33.997369Z +f1779b89f1e882bfe22d720ea9262390 +2009-08-13T15:24:35.589450Z +130 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +627 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/text-base/run.svn-base new file mode 100644 index 000000000..350c2bcb9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/.svn/text-base/run.svn-base @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator 10000 100 > d +awk '{if ($1 != 2) print $0}' < d > data +awk '{if ($1 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new R-Tree +../RTreeLoad data tree 20 10NN + +echo Querying R-Tree +../RTreeQuery queries tree 10NN > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t 10NN > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/run new file mode 100755 index 000000000..350c2bcb9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test1/run @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator 10000 100 > d +awk '{if ($1 != 2) print $0}' < d > data +awk '{if ($1 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new R-Tree +../RTreeLoad data tree 20 10NN + +echo Querying R-Tree +../RTreeQuery queries tree 10NN > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t 10NN > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/all-wcprops new file mode 100644 index 000000000..693c12f57 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/136/spatialindex/trunk/regressiontest/rtree/test2 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/130/spatialindex/trunk/regressiontest/rtree/test2/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/dir-prop-base new file mode 100644 index 000000000..4d3f4094b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 4 +mix + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/entries new file mode 100644 index 000000000..421efd4e2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/rtree/test2 +http://svn.gispython.org/spatialindex + + + +2009-08-19T15:24:15.611139Z +136 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.013138Z +9acfc48b3c207cd65522443a6a4ee9dd +2009-08-13T15:24:35.589450Z +130 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +486 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/text-base/run.svn-base new file mode 100644 index 000000000..9e7ccf2fa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/.svn/text-base/run.svn-base @@ -0,0 +1,23 @@ +#! /bin/bash + +echo Generating dataset +../Generator 10000 100 > mix + +echo Creating new R-Tree and Querying +../RTreeLoad mix tree 20 intersection > res + +echo Running exhaustive search +../Exhaustive mix intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/run new file mode 100755 index 000000000..9e7ccf2fa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test2/run @@ -0,0 +1,23 @@ +#! /bin/bash + +echo Generating dataset +../Generator 10000 100 > mix + +echo Creating new R-Tree and Querying +../RTreeLoad mix tree 20 intersection > res + +echo Running exhaustive search +../Exhaustive mix intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/all-wcprops new file mode 100644 index 000000000..cfbd70929 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/181/spatialindex/trunk/regressiontest/rtree/test3 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/181/spatialindex/trunk/regressiontest/rtree/test3/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/dir-prop-base new file mode 100644 index 000000000..a9b1f04be --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/dir-prop-base @@ -0,0 +1,8 @@ +K 10 +svn:ignore +V 15 +d +data +queries + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/entries new file mode 100644 index 000000000..1a5c24425 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/rtree/test3 +http://svn.gispython.org/spatialindex + + + +2010-04-12T17:07:13.774013Z +181 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.013138Z +e0262019820ab52ac9bd600911e49116 +2010-04-12T17:07:13.774013Z +181 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +739 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/text-base/run.svn-base new file mode 100644 index 000000000..3392dcb1b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/.svn/text-base/run.svn-base @@ -0,0 +1,30 @@ +#! /bin/bash + +export PATH=$PATH:../../.. + +#echo Generating 10 million entries. This might take a while +#echo Generating dataset +../Generator 1000000 0 > d +awk '{if ($1 == 1) print $0}' < d > data +awk '{if ($1 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new R-Tree +../RTreeBulkLoad data tree 1000 0.9 + +echo Querying R-Tree +../RTreeQuery queries tree intersection > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then echo "Same results with exhaustive search. Everything seems fine." +else echo "PROBLEM! We got different results from exhaustive search!" +fi +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/run new file mode 100755 index 000000000..3392dcb1b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test3/run @@ -0,0 +1,30 @@ +#! /bin/bash + +export PATH=$PATH:../../.. + +#echo Generating 10 million entries. This might take a while +#echo Generating dataset +../Generator 1000000 0 > d +awk '{if ($1 == 1) print $0}' < d > data +awk '{if ($1 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new R-Tree +../RTreeBulkLoad data tree 1000 0.9 + +echo Querying R-Tree +../RTreeQuery queries tree intersection > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t intersection > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then echo "Same results with exhaustive search. Everything seems fine." +else echo "PROBLEM! We got different results from exhaustive search!" +fi +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/all-wcprops new file mode 100644 index 000000000..ce1cd5e26 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/136/spatialindex/trunk/regressiontest/rtree/test4 +END +run +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/rtree/test4/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/dir-prop-base new file mode 100644 index 000000000..3359090b2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 13 +data +queries + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/entries new file mode 100644 index 000000000..0f02ec24f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/rtree/test4 +http://svn.gispython.org/spatialindex + + + +2009-08-19T15:24:15.611139Z +136 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.041166Z +d8cd8171ed1338905973134f9f2f189c +2007-08-01T20:37:49.786254Z +2 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +637 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/text-base/run.svn-base new file mode 100644 index 000000000..8bef71b9c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/.svn/text-base/run.svn-base @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator 10000 0 > d +awk '{if ($1 == 1) print $0}' < d > data +awk '{if ($1 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new R-Tree +../RTreeLoad data tree 20 selfjoin + +echo Querying R-Tree +../RTreeQuery queries tree selfjoin > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t selfjoin > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/run new file mode 100755 index 000000000..8bef71b9c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/rtree/test4/run @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator 10000 0 > d +awk '{if ($1 == 1) print $0}' < d > data +awk '{if ($1 == 2) print $0}' < d > queries +rm -rf d + +echo Creating new R-Tree +../RTreeLoad data tree 20 selfjoin + +echo Querying R-Tree +../RTreeQuery queries tree selfjoin > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t selfjoin > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/all-wcprops new file mode 100644 index 000000000..9a33cca87 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/all-wcprops @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/177/spatialindex/trunk/regressiontest/tprtree +END +TPRTreeQuery.cc +K 25 +svn:wc:ra_dav:version-url +V 84 +/spatialindex/!svn/ver/159/spatialindex/trunk/regressiontest/tprtree/TPRTreeQuery.cc +END +Exhaustive.cc +K 25 +svn:wc:ra_dav:version-url +V 82 +/spatialindex/!svn/ver/171/spatialindex/trunk/regressiontest/tprtree/Exhaustive.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 79 +/spatialindex/!svn/ver/45/spatialindex/trunk/regressiontest/tprtree/Makefile.am +END +TPRTreeLoad.cc +K 25 +svn:wc:ra_dav:version-url +V 83 +/spatialindex/!svn/ver/159/spatialindex/trunk/regressiontest/tprtree/TPRTreeLoad.cc +END +Generator.cc +K 25 +svn:wc:ra_dav:version-url +V 81 +/spatialindex/!svn/ver/159/spatialindex/trunk/regressiontest/tprtree/Generator.cc +END +RandomGenerator.cc +K 25 +svn:wc:ra_dav:version-url +V 86 +/spatialindex/!svn/ver/33/spatialindex/trunk/regressiontest/tprtree/RandomGenerator.cc +END +RandomGenerator.h +K 25 +svn:wc:ra_dav:version-url +V 85 +/spatialindex/!svn/ver/33/spatialindex/trunk/regressiontest/tprtree/RandomGenerator.h +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/dir-prop-base new file mode 100644 index 000000000..7a64f684a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/dir-prop-base @@ -0,0 +1,13 @@ +K 10 +svn:ignore +V 79 +Makefile.in +Exhaustive +TPRTreeLoad +Generator +.libs +.deps +TPRTreeQuery +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/entries new file mode 100644 index 000000000..96a10fc75 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/entries @@ -0,0 +1,272 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/tprtree +http://svn.gispython.org/spatialindex + + + +2010-03-05T02:56:08.483796Z +177 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +TPRTreeQuery.cc +file + + + + +2011-08-01T00:42:34.157878Z +2f27d0d210ed9bfa79b33129ca241216 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +8486 + +test1 +dir + +test2 +dir + +Exhaustive.cc +file + + + + +2011-08-01T00:42:34.157878Z +b19017e32516181ba22d090ed4193b4c +2009-12-29T02:35:01.217521Z +171 +hobu + + + + + + + + + + + + + + + + + + + + + +6368 + +Makefile.am +file + + + + +2011-08-01T00:42:34.157878Z +1a96c16fc63a9fa550021027cd994742 +2008-01-17T23:34:01.575758Z +45 +hobu + + + + + + + + + + + + + + + + + + + + + +527 + +TPRTreeLoad.cc +file + + + + +2011-08-01T00:42:34.157878Z +f30e8d027f206e8b447b9346258abba0 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +6388 + +Generator.cc +file + + + + +2011-08-01T00:42:34.157878Z +9a7e1fa26d98c69faf729f6a62c89a1d +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +2478 + +RandomGenerator.cc +file + + + + +2011-08-01T00:42:34.161195Z +9815f67f60f52f3a96132401716eec3d +2007-11-29T21:48:42.077730Z +33 +mhadji + + + + + + + + + + + + + + + + + + + + + +5120 + +RandomGenerator.h +file + + + + +2011-08-01T00:42:34.161195Z +8308d1342713b6b403aae9992cbaac93 +2007-11-29T21:48:42.077730Z +33 +mhadji + + + + + + + + + + + + + + + + + + + + + +3198 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Exhaustive.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Exhaustive.cc.svn-base new file mode 100644 index 000000000..2fe6ca848 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Exhaustive.cc.svn-base @@ -0,0 +1,272 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <assert.h> +#include <iostream> +#include <fstream> +#include <map> +#include <queue> +#include <cmath> +#include <stdint.h> + +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + +// Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html +#pragma warning( disable: 4251 ) + +#else + #include <stdint.h> +#endif + +class Rectangle +{ +public: + Rectangle(double xlow, double xhigh, double ylow, double yhigh) + : m_xlow(xlow), m_xhigh(xhigh), m_ylow(ylow), m_yhigh(yhigh) {} + + size_t computeCode(double x, double y) + { + size_t c = 0; + if(y > m_yhigh) c |= TOP; + else if(y < m_ylow) c |= BOTTOM; + if( x > m_xhigh) c |= RIGHT; + else if(x < m_xlow) c |= LEFT; + return c; + } + + bool intersectsPoint(double x, double y) + { + if (m_xlow <= x && x <= m_xhigh && + m_ylow <= y && y <= m_yhigh) return true; + return false; + } + + bool intersectsSegment(double x0, double x1, double y0, double y1) + { + size_t C0, C1, C; + double x,y; + + C0 = computeCode(x0, y0); + C1 = computeCode(x1, y1); + + for(;;) + { + /* + * trivial accept: both ends inside rectangle + */ + if((C0 | C1) == 0) + { + return true; + } + + /* + * trivial reject: both ends on the external side + * of the rectanlge + */ + if((C0 & C1) != 0) + { + return false; + } + + /* + * normal case: clip end outside rectangle + */ + C = C0 ? C0 : C1; + if(C & TOP) + { + x = x0 + (x1 - x0) * (m_yhigh - y0) / (y1 - y0); + y = m_yhigh; + } + else if(C & BOTTOM) + { + x = x0 + (x1 - x0) * (m_ylow - y0) / (y1 - y0); + y = m_ylow; + } + else if(C & RIGHT) + { + x = m_xhigh; + y = y0 + (y1 - y0) * (m_xhigh - x0) / (x1 - x0); + } + else + { + x = m_xlow; + y = y0 + (y1 - y0) * (m_xlow - x0) / (x1 - x0); + } + + /* + * set new end point and iterate + */ + if(C == C0) + { + x0 = x; y0 = y; + C0 = computeCode(x0, y0); + } + else + { + x1 =x; y1 = y; + C1 = computeCode(x1, y1); + } + } + } + + static const size_t TOP = 0x1; + static const size_t BOTTOM = 0x2; + static const size_t RIGHT = 0x4; + static const size_t LEFT = 0x8; + + double m_xlow, m_xhigh, m_ylow, m_yhigh; +}; + +class MovingPoint +{ +public: + MovingPoint(double ax, double vx, double ay, double vy, double rt) + : m_ax(ax), m_vx(vx), m_ay(ay), m_vy(vy), m_rt(rt) {} + + double getX(double t) { return m_ax + m_vx * (t - m_rt); } + double getY(double t) { return m_ay + m_vy * (t - m_rt); } + + double m_ax, m_vx, m_ay, m_vy; + double m_rt; +}; + +class TimeRectangle +{ +public: + TimeRectangle(double xlow, double xhigh, double ylow, double yhigh, double tlow, double thigh) + : m_xlow(xlow), m_xhigh(xhigh), m_ylow(ylow), m_yhigh(yhigh), m_tlow(tlow), m_thigh(thigh) {} + + bool intersects(MovingPoint& mp) + { + double x0 = mp.getX(m_tlow); + double x1 = mp.getX(m_thigh); + double y0 = mp.getY(m_tlow); + double y1 = mp.getY(m_thigh); + //double t0 = m_tlow; + //double t1 = m_thigh; + + Rectangle rxy(m_xlow, m_xhigh, m_ylow, m_yhigh); + return rxy.intersectsSegment(x0, x1, y0, y1); + +/* + // not needed to check all planes since it is + // guaranteed that on the time dimension + // the line segment and the query cube have + // exactly the same length (thus, if they intersect + // they should intersect on the X-Y projection for sure). + + Rectangle rxy(m_xlow, m_xhigh, m_ylow, m_yhigh); + if (rxy.intersectsSegment(x0, x1, y0, y1)) + { + Rectangle rxt(m_xlow, m_xhigh, m_tlow, m_thigh); + if (rxt.intersectsSegment(x0, x1, t0, t1)) + { + Rectangle ryt(m_ylow, m_yhigh, m_tlow, m_thigh); + if (ryt.intersectsSegment(y0, y1, t0, t1)) return true; + } + } +*/ + + return false; + } + + bool intersectsStupid(MovingPoint& mp) + { + size_t t0 = static_cast<size_t>(std::floor(m_tlow)); + size_t t1 = static_cast<size_t>(std::floor(m_thigh)); + + Rectangle rxy(m_xlow, m_xhigh, m_ylow, m_yhigh); + + for (size_t T = t0; T <= t1; T++) + { + if (rxy.intersectsPoint(mp.getX(T), mp.getY(T))) return true; + } + return false; + } + + double m_xlow, m_xhigh, m_ylow, m_yhigh; + double m_tlow, m_thigh; +}; + +int main(int argc, char** argv) +{ + if (argc != 2) + { + cerr << "Usage: " << argv[0] << " data_file." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file" << argv[1] << "." << endl; + return -1; + } + + map<size_t, MovingPoint> data; + size_t id, op; + double ax, vx, ay, vy, ct, rt, unused; + + while (fin) + { + fin >> id >> op >> ct >> rt >> unused >> ax >> vx >> unused >> ay >> vy; + if (! fin.good()) continue; + + if (op == INSERT) + { + data.insert(pair<size_t, MovingPoint>(id, MovingPoint(ax, vx, ay, vy, ct))); + } + else if (op == DELETE) + { + data.erase(id); + } + else if (op == QUERY) + { + TimeRectangle query = TimeRectangle(ax, vx, ay, vy, ct, rt); + for (multimap<size_t, MovingPoint>::iterator it = data.begin(); it != data.end(); it++) + { + //assert(query.intersects((*it).second) == query.intersectsStupid((*it).second)); + if (query.intersects((*it).second) == false && query.intersectsStupid((*it).second) == true) + { + cerr << "Something is wrong: " << ct << " " << (*it).first << endl; + return -1; + } + if (query.intersects((*it).second)) cout << (*it).first << endl; + } + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Generator.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Generator.cc.svn-base new file mode 100644 index 000000000..3a4ce6ad3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Generator.cc.svn-base @@ -0,0 +1,98 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "RandomGenerator.h" + +int main(int argc, char** argv) +{ + size_t ds = 1000, sl = 100, mui = 20, id = UNIFORM; + double a = 0.01; + + for (int i = 1; i < argc; i++) + { + if (! strcmp(argv[i], "-ds")) + { + i++; + if (i >= argc) + { + cerr << "Missing dataset size." << endl; + return -1; + } + ds = atoi(argv[i]); + } + else if (! strcmp(argv[i], "-sl")) + { + i++; + if (i >= argc) + { + cerr << "Missing simulation length." << endl; + return -1; + } + sl = atoi(argv[i]); + } + else if (! strcmp(argv[i], "-a")) + { + i++; + if (i >= argc) + { + cerr << "Missing agility." << endl; + return -1; + } + a = atof(argv[i]); + } + else if (! strcmp(argv[i], "-mui")) + { + i++; + if (i >= argc) + { + cerr << "Missing update rate." << endl; + return -1; + } + mui = atoi(argv[i]); + } + else + { + cerr << "Usage: " << endl + << " -ds dataset size" << endl + << " -sl simulation length" << endl + << " -a agility" << endl + << " -sd speed distribution" << endl + << " -id initial distribution" << endl + << " -mui maximum update interval" << endl; + return -1; + } + } + + RandomGenerator g = RandomGenerator(ds, sl, mui, a); + g.m_initialDistribution = id; + g.m_maxX = 1.0; g.m_maxY = 1.0; + g.m_minQueryExtent = 0.05; g.m_maxQueryExtent = 0.1; + g.m_minSpeed = 0.0025; // 15 miles/hour = 0.25 miles/minute + g.m_maxSpeed = 0.0166; // 100 miles/hour = 1.66 miles/minute + g.m_speedMean = 0.005; // 30 miles/hour = 0.5 miles/minute + g.m_speedStandardDeviation = 0.0033; // 20 miles/hour = 0.33 miles/minute + + g.generate(); +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..da64516f7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,11 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_PROGRAMS = Generator Exhaustive TPRTreeLoad TPRTreeQuery +INCLUDES = -I../../include +Generator_SOURCES = RandomGenerator.cc Generator.cc RandomGenerator.h +Generator_LDADD = ../../libspatialindex.la +Exhaustive_SOURCES = Exhaustive.cc +Exhaustive_LDADD = ../../libspatialindex.la +TPRTreeLoad_SOURCES = TPRTreeLoad.cc +TPRTreeLoad_LDADD = ../../libspatialindex.la +TPRTreeQuery_SOURCES = TPRTreeQuery.cc +TPRTreeQuery_LDADD = ../../libspatialindex.la diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/RandomGenerator.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/RandomGenerator.cc.svn-base new file mode 100644 index 000000000..df4f396e8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/RandomGenerator.cc.svn-base @@ -0,0 +1,176 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "RandomGenerator.h" + +RandomGenerator::MyMovingObject* RandomGenerator::createObject(int id, int st, double xmin, double xmax, double ymin, double ymax) +{ + double x, y; + x = m_random.nextUniformDouble(xmin, xmax); + y = m_random.nextUniformDouble(ymin, ymax); + + return createObject(id, st, x, y); +} + +RandomGenerator::MyMovingObject* RandomGenerator::createObject(int id, int st, double x, double y) +{ + MyMovingObject* o = new MyMovingObject(); + + o->m_id = id; + o->m_sx = x; + o->m_sy = y; + o->m_st = st; + o->m_kt = -1; + + double v = generateSpeed(); + if (m_random.flipCoin()) v *= -1.0; + + double angle = m_random.nextUniformDouble(-M_PI_2 , M_PI_2); + if (m_random.flipCoin()) angle *= -1.0; + + o->m_vx = cos(angle) * v; + o->m_vy = sin(angle) * v; + + cout << o->m_id << " " << INSERT << " " << st << " " << o->m_st << " 1 " << o->m_sx << " " << o->m_vx + << " 1 " << o->m_sy << " " << o->m_vy << endl; + + map<int, MyMovingObject*>::iterator itDataset = m_dataset.find(o->m_id); + if (itDataset != m_dataset.end()) m_dataset.erase(itDataset); + m_dataset.insert(pair<int, MyMovingObject*>(o->m_id, o)); + + int t1 = o->m_st + m_maximumUpdateInterval; + int t2; + + for (t2 = st; t2 <= m_simulationLength; t2++) + { + if (o->getX(t2) > m_maxX || o->getY(t2) > m_maxY || o->getX(t2) < 0.0 || o->getY(t2) < 0.0) break; + } + + o->m_outOfBounds = (t2 < t1) ? true : false; + int t = min(t1, t2); + + if (t == st) t++; + if (t < m_simulationLength) + { + m_updateArray[t].insert(o->m_id); + o->m_kt = t; + } + + return o; +} + +double RandomGenerator::generateSpeed() +{ + return m_random.nextUniformDouble(m_minSpeed, m_maxSpeed); +} + +void RandomGenerator::generate() +{ + for (map<int, MyMovingObject*>::iterator itDataset = m_dataset.begin(); itDataset != m_dataset.end(); itDataset++) + { + delete (*itDataset).second; + } + m_dataset.clear(); + + for (int cIndex = 0; cIndex < m_simulationLength; cIndex++) + { + m_updateArray[cIndex].clear(); + } + + int updatesPerTimeInstant = (int) ceil(((double) m_datasetSize) * m_agility); + + for (int cObject = 0; cObject < m_datasetSize; cObject++) + { + createObject(cObject, 0, 0.0, m_maxX, 0.0, m_maxY); + + if (cObject % 10000 == 0) cerr << cObject << endl; + } + + for (int Tnow = 1; Tnow < m_simulationLength; Tnow++) + { + cerr << "Time: " << Tnow; + + int cTotalUpdates = 0; + int cNeedToUpdate = updatesPerTimeInstant; + set<int> updated; + set<int>::iterator itUpdateArray = m_updateArray[Tnow].begin(); + + while (cNeedToUpdate > 0 || itUpdateArray != m_updateArray[Tnow].end()) + { + int id; + bool bKilled = false; + if (itUpdateArray != m_updateArray[Tnow].end()) + { + bKilled = true; + id = *itUpdateArray; + itUpdateArray++; + } + else + { + id = m_random.nextUniformLong(0, m_datasetSize); + set<int>::iterator itUpdated = updated.find(id); + + while (itUpdated != updated.end()) + { + id = m_random.nextUniformLong(0, m_datasetSize); + itUpdated = updated.find(id); + } + } + updated.insert(id); + cNeedToUpdate--; + cTotalUpdates++; + + map<int,MyMovingObject*>::iterator itDataset = m_dataset.find(id); + assert(itDataset != m_dataset.end()); + MyMovingObject* o = (*itDataset).second; + m_dataset.erase(itDataset); + if (o->m_kt >= 0) m_updateArray[o->m_kt].erase(o->m_id); + + cout << o->m_id << " " << DELETE << " " << Tnow << " " << o->m_st << " 1 " << o->m_sx << " " << o->m_vx + << " 1 " << o->m_sy << " " << o->m_vy << endl; + + if (bKilled && o->m_outOfBounds) + { + createObject(o->m_id, Tnow, 0.0, m_maxX, 0.0, m_maxY); + } + else + { + createObject(o->m_id, Tnow, o->getX(Tnow), o->getY(Tnow)); + } + + delete o; + } + + for (int cQuery = 0; cQuery < m_queriesPerTimeInstant; cQuery++) + { + double x = m_random.nextUniformDouble(0.0, m_maxX); + double y = m_random.nextUniformDouble(0.0, m_maxY); + double dx = m_random.nextUniformDouble(m_minQueryExtent, m_maxQueryExtent); + double dy = m_random.nextUniformDouble(m_minQueryExtent, m_maxQueryExtent); + int dt = m_random.nextUniformLong(m_minQueryInterval, m_maxQueryInterval); + int t = m_random.nextUniformLong(Tnow, Tnow + m_horizon - dt); + + cout << "9999999 " << QUERY << " " << t << " " << t + dt << " 1 " << x - dx << " " << x + dx << " 1 " << y - dy << " " << y + dy << endl; + } + + cerr << ", Updates: " << cTotalUpdates << endl; + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/RandomGenerator.h.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/RandomGenerator.h.svn-base new file mode 100644 index 000000000..9748fb0bd --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/RandomGenerator.h.svn-base @@ -0,0 +1,138 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#ifndef _random_generator_h +#define _random_generator_h + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <errno.h> +#include <math.h> + +#include <string> +#include <iostream> +#include <fstream> +#include <cmath> +#include <sstream> +#include <vector> +#include <map> +#include <set> +#include <stack> + +#include <tools/Tools.h> + +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +#define UNIFORM 1 + +class RandomGenerator +{ +public: + RandomGenerator(int ds, int sl, int mui, double a) + : m_datasetSize(ds), + m_simulationLength(sl), + m_initialDistribution(UNIFORM), + m_maximumUpdateInterval(mui), + m_queriesPerTimeInstant(5), + m_minQueryExtent(5), + m_maxQueryExtent(10), + m_horizon(20), + m_maxQueryInterval(10), + m_minQueryInterval(2), + m_agility(a), + m_minSpeed(0.25), // 15 miles/hour = 0.25 miles/minute + m_maxSpeed(1.66), // 100 miles/hour = 1.66 miles/minute + m_speedMean(0.5), // 30 miles/hour = 0.5 miles/minute + m_speedStandardDeviation(0.33), // 20 miles/hour = 0.33 miles/minute + m_maxX(100.0), + m_maxY(100.0), + m_updateArray(0) + { + m_updateArray = new set<int>[m_simulationLength]; + } + + virtual ~RandomGenerator() + { + for (map<int, MyMovingObject*>::iterator it = m_dataset.begin(); it != m_dataset.end(); it++) + { + delete (*it).second; + } + delete[] m_updateArray; + } + + class MyMovingObject + { + public: + double getX(int t) + { + return m_sx + m_vx * (t - m_st); + } + + double getY(int t) + { + return m_sy + m_vy * (t - m_st); + } + + public: + int m_id; + int m_st; + int m_kt; + double m_sx, m_sy; + double m_vx, m_vy; + bool m_outOfBounds; + }; + + virtual void generate(); + MyMovingObject* createObject(int id, int st, double xmin, double xmax, double ymin, double ymax); + MyMovingObject* createObject(int id, int st, double x, double y); + double generateSpeed(); + +public: + int m_datasetSize; + int m_simulationLength; + int m_initialDistribution; + int m_maximumUpdateInterval; + int m_queriesPerTimeInstant; + double m_minQueryExtent; + double m_maxQueryExtent; + int m_horizon; + int m_maxQueryInterval; + int m_minQueryInterval; + double m_agility; + double m_minSpeed; + double m_maxSpeed; + double m_speedMean; + double m_speedStandardDeviation; + double m_maxX; + double m_maxY; + + map<int, MyMovingObject*> m_dataset; + set<int>* m_updateArray; + Tools::Random m_random; +}; + +#endif diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/TPRTreeLoad.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/TPRTreeLoad.cc.svn-base new file mode 100644 index 000000000..084396bcc --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/TPRTreeLoad.cc.svn-base @@ -0,0 +1,197 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +// include library header file. + +#include <SpatialIndex.h> + +#include <limits> + +using namespace SpatialIndex; +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// see RTreeQuery for a more elaborate example. +class MyVisitor : public IVisitor +{ +public: + void visitNode(const INode& n) {} + + void visitData(const IData& d) + { + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 4) + { + cerr << "Usage: " << argv[0] << " input_file tree_file capacity." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file " << argv[1] << "." << endl; + return -1; + } + + // Create a new storage manager with the provided base name and a 4K page size. + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // Create a new, empty, TPRTree with dimensionality 2, minimum load 70%, horizon 20 time instants, using "file" as + // the StorageManager and the TPRSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = TPRTree::createNewTPRTree(*file, 0.7, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::TPRTree::TPRV_RSTAR, 20, indexIdentifier); + + size_t count = 0; + id_type id; + size_t op; + double ax, vx, ay, vy, ct, rt, unused; + double plow[2], phigh[2]; + double pvlow[2], pvhigh[2]; + + while (fin) + { + fin >> id >> op >> ct >> rt >> unused >> ax >> vx >> unused >> ay >> vy; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(ct, std::numeric_limits<double>::max()); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + //ostringstream os; + //os << r; + //string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see RTree::Node::load and RTree::Node::store for + // an example of how to do that). + + //tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(rt, ct); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + if (tree->deleteData(r, id) == false) + { + cerr << "******ERROR******" << endl; + cerr << "Cannot delete id: " << id << " , count: " << count << endl; + return -1; + } + } + else if (op == QUERY) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = vx; phigh[1] = vy; + pvlow[0] = 0.0; pvlow[1] = 0.0; + pvhigh[0] = 0.0; pvhigh[1] = 0.0; + + Tools::Interval ivT(ct, rt); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + MyVisitor vis; + + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Buffer hits: " << file->getHits() << endl; + cerr << "Index ID: " << indexIdentifier << endl; + + bool ret = tree->isIndexValid(); + if (ret == false) cerr << "ERROR: Structure is invalid!" << endl; + else cerr << "The stucture seems O.K." << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/TPRTreeQuery.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/TPRTreeQuery.cc.svn-base new file mode 100644 index 000000000..52ae42f58 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/.svn/text-base/TPRTreeQuery.cc.svn-base @@ -0,0 +1,298 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +// include library header file. + +#include <SpatialIndex.h> + +#include <limits> + +using namespace SpatialIndex; +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// findes the index and leaf IO for answering the query and prints +// the resulting data IDs to stdout. +class MyVisitor : public IVisitor +{ +public: + size_t m_indexIO; + size_t m_leafIO; + +public: + MyVisitor() : m_indexIO(0), m_leafIO(0) {} + + void visitNode(const INode& n) + { + if (n.isLeaf()) m_leafIO++; + else m_indexIO++; + } + + void visitData(const IData& d) + { + IShape* pS; + d.getShape(&pS); + // do something. + delete pS; + + // data should be an array of characters representing a Region as a string. + //byte* pData = 0; + //size_t cLen = 0; + //d.getData(cLen, &pData); + // do something. + //string s = reinterpret_cast<char*>(pData); + //cout << s << endl; + //delete[] pData; + + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +// example of a Strategy pattern. +// traverses the tree by level. +class MyQueryStrategy : public SpatialIndex::IQueryStrategy +{ +private: + queue<id_type> ids; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + IShape* ps; + entry.getShape(&ps); + MovingRegion* pr = dynamic_cast<MovingRegion*>(ps); + + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl << endl << endl; + // print node MBRs gnuplot style! + + delete ps; + + const INode* n = dynamic_cast<const INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 1) + { + for (size_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push(n->getChildIdentifier(cChild)); + } + } + + if (! ids.empty()) + { + nextEntry = ids.front(); ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } + } +}; + +// example of a Strategy pattern. +// find the total indexed space managed by the index (the MBR of the root). +class MyQueryStrategy2 : public IQueryStrategy +{ +public: + Region m_indexedSpace; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + // the first time we are called, entry points to the root. + + // stop after the root. + hasNext = false; + + IShape* ps; + entry.getShape(&ps); + ps->getMBR(m_indexedSpace); + delete ps; + } +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 3) + { + cerr << "Usage: " << argv[0] << " input_file tree_file." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file " << argv[1] << "." << endl; + return -1; + } + + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::loadDiskStorageManager(baseName); + // this will try to locate and open an already existing storage manager. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // If we need to open an existing tree stored in the storage manager, we only + // have to specify the index identifier as follows + ISpatialIndex* tree = TPRTree::loadTPRTree(*file, 1); + + size_t count = 0; + id_type id; + size_t op; + double ax, vx, ay, vy, ct, rt, unused; + double plow[2], phigh[2]; + double pvlow[2], pvhigh[2]; + size_t indexIO = 0; + size_t leafIO = 0; + + while (fin) + { + fin >> id >> op >> ct >> rt >> unused >> ax >> vx >> unused >> ay >> vy; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(ct, std::numeric_limits<double>::max()); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + //ostringstream os; + //os << r; + //string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see RTree::Node::load and RTree::Node::store for + // an example of how to do that). + + //tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(rt, ct); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + if (tree->deleteData(r, id) == false) + { + cerr << "******ERROR******" << endl; + cerr << "Cannot delete id: " << id << " , count: " << count << endl; + return -1; + } + } + else if (op == QUERY) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = vx; phigh[1] = vy; + pvlow[0] = 0.0; pvlow[1] = 0.0; + pvhigh[0] = 0.0; pvhigh[1] = 0.0; + + Tools::Interval ivT(ct, rt); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + MyVisitor vis; + + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + + indexIO += vis.m_indexIO; + leafIO += vis.m_leafIO; + // example of the Visitor pattern usage, for calculating how many nodes + // were visited. + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + MyQueryStrategy2 qs; + tree->queryStrategy(qs); + + cerr << "Indexed space: " << qs.m_indexedSpace << endl; + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Index I/O: " << indexIO << endl; + cerr << "Leaf I/O: " << leafIO << endl; + cerr << "Buffer hits: " << file->getHits() << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail writting the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Exhaustive.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Exhaustive.cc new file mode 100644 index 000000000..2fe6ca848 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Exhaustive.cc @@ -0,0 +1,272 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <assert.h> +#include <iostream> +#include <fstream> +#include <map> +#include <queue> +#include <cmath> +#include <stdint.h> + +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +#if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + +// Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html +#pragma warning( disable: 4251 ) + +#else + #include <stdint.h> +#endif + +class Rectangle +{ +public: + Rectangle(double xlow, double xhigh, double ylow, double yhigh) + : m_xlow(xlow), m_xhigh(xhigh), m_ylow(ylow), m_yhigh(yhigh) {} + + size_t computeCode(double x, double y) + { + size_t c = 0; + if(y > m_yhigh) c |= TOP; + else if(y < m_ylow) c |= BOTTOM; + if( x > m_xhigh) c |= RIGHT; + else if(x < m_xlow) c |= LEFT; + return c; + } + + bool intersectsPoint(double x, double y) + { + if (m_xlow <= x && x <= m_xhigh && + m_ylow <= y && y <= m_yhigh) return true; + return false; + } + + bool intersectsSegment(double x0, double x1, double y0, double y1) + { + size_t C0, C1, C; + double x,y; + + C0 = computeCode(x0, y0); + C1 = computeCode(x1, y1); + + for(;;) + { + /* + * trivial accept: both ends inside rectangle + */ + if((C0 | C1) == 0) + { + return true; + } + + /* + * trivial reject: both ends on the external side + * of the rectanlge + */ + if((C0 & C1) != 0) + { + return false; + } + + /* + * normal case: clip end outside rectangle + */ + C = C0 ? C0 : C1; + if(C & TOP) + { + x = x0 + (x1 - x0) * (m_yhigh - y0) / (y1 - y0); + y = m_yhigh; + } + else if(C & BOTTOM) + { + x = x0 + (x1 - x0) * (m_ylow - y0) / (y1 - y0); + y = m_ylow; + } + else if(C & RIGHT) + { + x = m_xhigh; + y = y0 + (y1 - y0) * (m_xhigh - x0) / (x1 - x0); + } + else + { + x = m_xlow; + y = y0 + (y1 - y0) * (m_xlow - x0) / (x1 - x0); + } + + /* + * set new end point and iterate + */ + if(C == C0) + { + x0 = x; y0 = y; + C0 = computeCode(x0, y0); + } + else + { + x1 =x; y1 = y; + C1 = computeCode(x1, y1); + } + } + } + + static const size_t TOP = 0x1; + static const size_t BOTTOM = 0x2; + static const size_t RIGHT = 0x4; + static const size_t LEFT = 0x8; + + double m_xlow, m_xhigh, m_ylow, m_yhigh; +}; + +class MovingPoint +{ +public: + MovingPoint(double ax, double vx, double ay, double vy, double rt) + : m_ax(ax), m_vx(vx), m_ay(ay), m_vy(vy), m_rt(rt) {} + + double getX(double t) { return m_ax + m_vx * (t - m_rt); } + double getY(double t) { return m_ay + m_vy * (t - m_rt); } + + double m_ax, m_vx, m_ay, m_vy; + double m_rt; +}; + +class TimeRectangle +{ +public: + TimeRectangle(double xlow, double xhigh, double ylow, double yhigh, double tlow, double thigh) + : m_xlow(xlow), m_xhigh(xhigh), m_ylow(ylow), m_yhigh(yhigh), m_tlow(tlow), m_thigh(thigh) {} + + bool intersects(MovingPoint& mp) + { + double x0 = mp.getX(m_tlow); + double x1 = mp.getX(m_thigh); + double y0 = mp.getY(m_tlow); + double y1 = mp.getY(m_thigh); + //double t0 = m_tlow; + //double t1 = m_thigh; + + Rectangle rxy(m_xlow, m_xhigh, m_ylow, m_yhigh); + return rxy.intersectsSegment(x0, x1, y0, y1); + +/* + // not needed to check all planes since it is + // guaranteed that on the time dimension + // the line segment and the query cube have + // exactly the same length (thus, if they intersect + // they should intersect on the X-Y projection for sure). + + Rectangle rxy(m_xlow, m_xhigh, m_ylow, m_yhigh); + if (rxy.intersectsSegment(x0, x1, y0, y1)) + { + Rectangle rxt(m_xlow, m_xhigh, m_tlow, m_thigh); + if (rxt.intersectsSegment(x0, x1, t0, t1)) + { + Rectangle ryt(m_ylow, m_yhigh, m_tlow, m_thigh); + if (ryt.intersectsSegment(y0, y1, t0, t1)) return true; + } + } +*/ + + return false; + } + + bool intersectsStupid(MovingPoint& mp) + { + size_t t0 = static_cast<size_t>(std::floor(m_tlow)); + size_t t1 = static_cast<size_t>(std::floor(m_thigh)); + + Rectangle rxy(m_xlow, m_xhigh, m_ylow, m_yhigh); + + for (size_t T = t0; T <= t1; T++) + { + if (rxy.intersectsPoint(mp.getX(T), mp.getY(T))) return true; + } + return false; + } + + double m_xlow, m_xhigh, m_ylow, m_yhigh; + double m_tlow, m_thigh; +}; + +int main(int argc, char** argv) +{ + if (argc != 2) + { + cerr << "Usage: " << argv[0] << " data_file." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file" << argv[1] << "." << endl; + return -1; + } + + map<size_t, MovingPoint> data; + size_t id, op; + double ax, vx, ay, vy, ct, rt, unused; + + while (fin) + { + fin >> id >> op >> ct >> rt >> unused >> ax >> vx >> unused >> ay >> vy; + if (! fin.good()) continue; + + if (op == INSERT) + { + data.insert(pair<size_t, MovingPoint>(id, MovingPoint(ax, vx, ay, vy, ct))); + } + else if (op == DELETE) + { + data.erase(id); + } + else if (op == QUERY) + { + TimeRectangle query = TimeRectangle(ax, vx, ay, vy, ct, rt); + for (multimap<size_t, MovingPoint>::iterator it = data.begin(); it != data.end(); it++) + { + //assert(query.intersects((*it).second) == query.intersectsStupid((*it).second)); + if (query.intersects((*it).second) == false && query.intersectsStupid((*it).second) == true) + { + cerr << "Something is wrong: " << ct << " " << (*it).first << endl; + return -1; + } + if (query.intersects((*it).second)) cout << (*it).first << endl; + } + } + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Generator.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Generator.cc new file mode 100644 index 000000000..3a4ce6ad3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Generator.cc @@ -0,0 +1,98 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "RandomGenerator.h" + +int main(int argc, char** argv) +{ + size_t ds = 1000, sl = 100, mui = 20, id = UNIFORM; + double a = 0.01; + + for (int i = 1; i < argc; i++) + { + if (! strcmp(argv[i], "-ds")) + { + i++; + if (i >= argc) + { + cerr << "Missing dataset size." << endl; + return -1; + } + ds = atoi(argv[i]); + } + else if (! strcmp(argv[i], "-sl")) + { + i++; + if (i >= argc) + { + cerr << "Missing simulation length." << endl; + return -1; + } + sl = atoi(argv[i]); + } + else if (! strcmp(argv[i], "-a")) + { + i++; + if (i >= argc) + { + cerr << "Missing agility." << endl; + return -1; + } + a = atof(argv[i]); + } + else if (! strcmp(argv[i], "-mui")) + { + i++; + if (i >= argc) + { + cerr << "Missing update rate." << endl; + return -1; + } + mui = atoi(argv[i]); + } + else + { + cerr << "Usage: " << endl + << " -ds dataset size" << endl + << " -sl simulation length" << endl + << " -a agility" << endl + << " -sd speed distribution" << endl + << " -id initial distribution" << endl + << " -mui maximum update interval" << endl; + return -1; + } + } + + RandomGenerator g = RandomGenerator(ds, sl, mui, a); + g.m_initialDistribution = id; + g.m_maxX = 1.0; g.m_maxY = 1.0; + g.m_minQueryExtent = 0.05; g.m_maxQueryExtent = 0.1; + g.m_minSpeed = 0.0025; // 15 miles/hour = 0.25 miles/minute + g.m_maxSpeed = 0.0166; // 100 miles/hour = 1.66 miles/minute + g.m_speedMean = 0.005; // 30 miles/hour = 0.5 miles/minute + g.m_speedStandardDeviation = 0.0033; // 20 miles/hour = 0.33 miles/minute + + g.generate(); +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Makefile.am b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Makefile.am new file mode 100644 index 000000000..da64516f7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/Makefile.am @@ -0,0 +1,11 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_PROGRAMS = Generator Exhaustive TPRTreeLoad TPRTreeQuery +INCLUDES = -I../../include +Generator_SOURCES = RandomGenerator.cc Generator.cc RandomGenerator.h +Generator_LDADD = ../../libspatialindex.la +Exhaustive_SOURCES = Exhaustive.cc +Exhaustive_LDADD = ../../libspatialindex.la +TPRTreeLoad_SOURCES = TPRTreeLoad.cc +TPRTreeLoad_LDADD = ../../libspatialindex.la +TPRTreeQuery_SOURCES = TPRTreeQuery.cc +TPRTreeQuery_LDADD = ../../libspatialindex.la diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/RandomGenerator.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/RandomGenerator.cc new file mode 100644 index 000000000..df4f396e8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/RandomGenerator.cc @@ -0,0 +1,176 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "RandomGenerator.h" + +RandomGenerator::MyMovingObject* RandomGenerator::createObject(int id, int st, double xmin, double xmax, double ymin, double ymax) +{ + double x, y; + x = m_random.nextUniformDouble(xmin, xmax); + y = m_random.nextUniformDouble(ymin, ymax); + + return createObject(id, st, x, y); +} + +RandomGenerator::MyMovingObject* RandomGenerator::createObject(int id, int st, double x, double y) +{ + MyMovingObject* o = new MyMovingObject(); + + o->m_id = id; + o->m_sx = x; + o->m_sy = y; + o->m_st = st; + o->m_kt = -1; + + double v = generateSpeed(); + if (m_random.flipCoin()) v *= -1.0; + + double angle = m_random.nextUniformDouble(-M_PI_2 , M_PI_2); + if (m_random.flipCoin()) angle *= -1.0; + + o->m_vx = cos(angle) * v; + o->m_vy = sin(angle) * v; + + cout << o->m_id << " " << INSERT << " " << st << " " << o->m_st << " 1 " << o->m_sx << " " << o->m_vx + << " 1 " << o->m_sy << " " << o->m_vy << endl; + + map<int, MyMovingObject*>::iterator itDataset = m_dataset.find(o->m_id); + if (itDataset != m_dataset.end()) m_dataset.erase(itDataset); + m_dataset.insert(pair<int, MyMovingObject*>(o->m_id, o)); + + int t1 = o->m_st + m_maximumUpdateInterval; + int t2; + + for (t2 = st; t2 <= m_simulationLength; t2++) + { + if (o->getX(t2) > m_maxX || o->getY(t2) > m_maxY || o->getX(t2) < 0.0 || o->getY(t2) < 0.0) break; + } + + o->m_outOfBounds = (t2 < t1) ? true : false; + int t = min(t1, t2); + + if (t == st) t++; + if (t < m_simulationLength) + { + m_updateArray[t].insert(o->m_id); + o->m_kt = t; + } + + return o; +} + +double RandomGenerator::generateSpeed() +{ + return m_random.nextUniformDouble(m_minSpeed, m_maxSpeed); +} + +void RandomGenerator::generate() +{ + for (map<int, MyMovingObject*>::iterator itDataset = m_dataset.begin(); itDataset != m_dataset.end(); itDataset++) + { + delete (*itDataset).second; + } + m_dataset.clear(); + + for (int cIndex = 0; cIndex < m_simulationLength; cIndex++) + { + m_updateArray[cIndex].clear(); + } + + int updatesPerTimeInstant = (int) ceil(((double) m_datasetSize) * m_agility); + + for (int cObject = 0; cObject < m_datasetSize; cObject++) + { + createObject(cObject, 0, 0.0, m_maxX, 0.0, m_maxY); + + if (cObject % 10000 == 0) cerr << cObject << endl; + } + + for (int Tnow = 1; Tnow < m_simulationLength; Tnow++) + { + cerr << "Time: " << Tnow; + + int cTotalUpdates = 0; + int cNeedToUpdate = updatesPerTimeInstant; + set<int> updated; + set<int>::iterator itUpdateArray = m_updateArray[Tnow].begin(); + + while (cNeedToUpdate > 0 || itUpdateArray != m_updateArray[Tnow].end()) + { + int id; + bool bKilled = false; + if (itUpdateArray != m_updateArray[Tnow].end()) + { + bKilled = true; + id = *itUpdateArray; + itUpdateArray++; + } + else + { + id = m_random.nextUniformLong(0, m_datasetSize); + set<int>::iterator itUpdated = updated.find(id); + + while (itUpdated != updated.end()) + { + id = m_random.nextUniformLong(0, m_datasetSize); + itUpdated = updated.find(id); + } + } + updated.insert(id); + cNeedToUpdate--; + cTotalUpdates++; + + map<int,MyMovingObject*>::iterator itDataset = m_dataset.find(id); + assert(itDataset != m_dataset.end()); + MyMovingObject* o = (*itDataset).second; + m_dataset.erase(itDataset); + if (o->m_kt >= 0) m_updateArray[o->m_kt].erase(o->m_id); + + cout << o->m_id << " " << DELETE << " " << Tnow << " " << o->m_st << " 1 " << o->m_sx << " " << o->m_vx + << " 1 " << o->m_sy << " " << o->m_vy << endl; + + if (bKilled && o->m_outOfBounds) + { + createObject(o->m_id, Tnow, 0.0, m_maxX, 0.0, m_maxY); + } + else + { + createObject(o->m_id, Tnow, o->getX(Tnow), o->getY(Tnow)); + } + + delete o; + } + + for (int cQuery = 0; cQuery < m_queriesPerTimeInstant; cQuery++) + { + double x = m_random.nextUniformDouble(0.0, m_maxX); + double y = m_random.nextUniformDouble(0.0, m_maxY); + double dx = m_random.nextUniformDouble(m_minQueryExtent, m_maxQueryExtent); + double dy = m_random.nextUniformDouble(m_minQueryExtent, m_maxQueryExtent); + int dt = m_random.nextUniformLong(m_minQueryInterval, m_maxQueryInterval); + int t = m_random.nextUniformLong(Tnow, Tnow + m_horizon - dt); + + cout << "9999999 " << QUERY << " " << t << " " << t + dt << " 1 " << x - dx << " " << x + dx << " 1 " << y - dy << " " << y + dy << endl; + } + + cerr << ", Updates: " << cTotalUpdates << endl; + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/RandomGenerator.h b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/RandomGenerator.h new file mode 100644 index 000000000..9748fb0bd --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/RandomGenerator.h @@ -0,0 +1,138 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#ifndef _random_generator_h +#define _random_generator_h + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <errno.h> +#include <math.h> + +#include <string> +#include <iostream> +#include <fstream> +#include <cmath> +#include <sstream> +#include <vector> +#include <map> +#include <set> +#include <stack> + +#include <tools/Tools.h> + +using namespace std; + +#define DELETE 0 +#define INSERT 1 +#define QUERY 2 + +#define UNIFORM 1 + +class RandomGenerator +{ +public: + RandomGenerator(int ds, int sl, int mui, double a) + : m_datasetSize(ds), + m_simulationLength(sl), + m_initialDistribution(UNIFORM), + m_maximumUpdateInterval(mui), + m_queriesPerTimeInstant(5), + m_minQueryExtent(5), + m_maxQueryExtent(10), + m_horizon(20), + m_maxQueryInterval(10), + m_minQueryInterval(2), + m_agility(a), + m_minSpeed(0.25), // 15 miles/hour = 0.25 miles/minute + m_maxSpeed(1.66), // 100 miles/hour = 1.66 miles/minute + m_speedMean(0.5), // 30 miles/hour = 0.5 miles/minute + m_speedStandardDeviation(0.33), // 20 miles/hour = 0.33 miles/minute + m_maxX(100.0), + m_maxY(100.0), + m_updateArray(0) + { + m_updateArray = new set<int>[m_simulationLength]; + } + + virtual ~RandomGenerator() + { + for (map<int, MyMovingObject*>::iterator it = m_dataset.begin(); it != m_dataset.end(); it++) + { + delete (*it).second; + } + delete[] m_updateArray; + } + + class MyMovingObject + { + public: + double getX(int t) + { + return m_sx + m_vx * (t - m_st); + } + + double getY(int t) + { + return m_sy + m_vy * (t - m_st); + } + + public: + int m_id; + int m_st; + int m_kt; + double m_sx, m_sy; + double m_vx, m_vy; + bool m_outOfBounds; + }; + + virtual void generate(); + MyMovingObject* createObject(int id, int st, double xmin, double xmax, double ymin, double ymax); + MyMovingObject* createObject(int id, int st, double x, double y); + double generateSpeed(); + +public: + int m_datasetSize; + int m_simulationLength; + int m_initialDistribution; + int m_maximumUpdateInterval; + int m_queriesPerTimeInstant; + double m_minQueryExtent; + double m_maxQueryExtent; + int m_horizon; + int m_maxQueryInterval; + int m_minQueryInterval; + double m_agility; + double m_minSpeed; + double m_maxSpeed; + double m_speedMean; + double m_speedStandardDeviation; + double m_maxX; + double m_maxY; + + map<int, MyMovingObject*> m_dataset; + set<int>* m_updateArray; + Tools::Random m_random; +}; + +#endif diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/TPRTreeLoad.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/TPRTreeLoad.cc new file mode 100644 index 000000000..084396bcc --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/TPRTreeLoad.cc @@ -0,0 +1,197 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +// include library header file. + +#include <SpatialIndex.h> + +#include <limits> + +using namespace SpatialIndex; +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// see RTreeQuery for a more elaborate example. +class MyVisitor : public IVisitor +{ +public: + void visitNode(const INode& n) {} + + void visitData(const IData& d) + { + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 4) + { + cerr << "Usage: " << argv[0] << " input_file tree_file capacity." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file " << argv[1] << "." << endl; + return -1; + } + + // Create a new storage manager with the provided base name and a 4K page size. + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::createNewDiskStorageManager(baseName, 4096); + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // Create a new, empty, TPRTree with dimensionality 2, minimum load 70%, horizon 20 time instants, using "file" as + // the StorageManager and the TPRSTAR splitting policy. + id_type indexIdentifier; + ISpatialIndex* tree = TPRTree::createNewTPRTree(*file, 0.7, atoi(argv[3]), atoi(argv[3]), 2, SpatialIndex::TPRTree::TPRV_RSTAR, 20, indexIdentifier); + + size_t count = 0; + id_type id; + size_t op; + double ax, vx, ay, vy, ct, rt, unused; + double plow[2], phigh[2]; + double pvlow[2], pvhigh[2]; + + while (fin) + { + fin >> id >> op >> ct >> rt >> unused >> ax >> vx >> unused >> ay >> vy; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(ct, std::numeric_limits<double>::max()); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + //ostringstream os; + //os << r; + //string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see RTree::Node::load and RTree::Node::store for + // an example of how to do that). + + //tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(rt, ct); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + if (tree->deleteData(r, id) == false) + { + cerr << "******ERROR******" << endl; + cerr << "Cannot delete id: " << id << " , count: " << count << endl; + return -1; + } + } + else if (op == QUERY) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = vx; phigh[1] = vy; + pvlow[0] = 0.0; pvlow[1] = 0.0; + pvhigh[0] = 0.0; pvhigh[1] = 0.0; + + Tools::Interval ivT(ct, rt); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + MyVisitor vis; + + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Buffer hits: " << file->getHits() << endl; + cerr << "Index ID: " << indexIdentifier << endl; + + bool ret = tree->isIndexValid(); + if (ret == false) cerr << "ERROR: Structure is invalid!" << endl; + else cerr << "The stucture seems O.K." << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail trying to write the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/TPRTreeQuery.cc b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/TPRTreeQuery.cc new file mode 100644 index 000000000..52ae42f58 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/TPRTreeQuery.cc @@ -0,0 +1,298 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +// NOTE: Please read README.txt before browsing this code. + +// include library header file. + +#include <SpatialIndex.h> + +#include <limits> + +using namespace SpatialIndex; +using namespace std; + +#define INSERT 1 +#define DELETE 0 +#define QUERY 2 + +// example of a Visitor pattern. +// findes the index and leaf IO for answering the query and prints +// the resulting data IDs to stdout. +class MyVisitor : public IVisitor +{ +public: + size_t m_indexIO; + size_t m_leafIO; + +public: + MyVisitor() : m_indexIO(0), m_leafIO(0) {} + + void visitNode(const INode& n) + { + if (n.isLeaf()) m_leafIO++; + else m_indexIO++; + } + + void visitData(const IData& d) + { + IShape* pS; + d.getShape(&pS); + // do something. + delete pS; + + // data should be an array of characters representing a Region as a string. + //byte* pData = 0; + //size_t cLen = 0; + //d.getData(cLen, &pData); + // do something. + //string s = reinterpret_cast<char*>(pData); + //cout << s << endl; + //delete[] pData; + + cout << d.getIdentifier() << endl; + // the ID of this data entry is an answer to the query. I will just print it to stdout. + } + + void visitData(std::vector<const IData*>& v) {} +}; + +// example of a Strategy pattern. +// traverses the tree by level. +class MyQueryStrategy : public SpatialIndex::IQueryStrategy +{ +private: + queue<id_type> ids; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + IShape* ps; + entry.getShape(&ps); + MovingRegion* pr = dynamic_cast<MovingRegion*>(ps); + + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pLow[1] << endl; + cout << pr->m_pHigh[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pHigh[1] << endl; + cout << pr->m_pLow[0] << " " << pr->m_pLow[1] << endl << endl << endl; + // print node MBRs gnuplot style! + + delete ps; + + const INode* n = dynamic_cast<const INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 1) + { + for (size_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push(n->getChildIdentifier(cChild)); + } + } + + if (! ids.empty()) + { + nextEntry = ids.front(); ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } + } +}; + +// example of a Strategy pattern. +// find the total indexed space managed by the index (the MBR of the root). +class MyQueryStrategy2 : public IQueryStrategy +{ +public: + Region m_indexedSpace; + +public: + void getNextEntry(const IEntry& entry, id_type& nextEntry, bool& hasNext) + { + // the first time we are called, entry points to the root. + + // stop after the root. + hasNext = false; + + IShape* ps; + entry.getShape(&ps); + ps->getMBR(m_indexedSpace); + delete ps; + } +}; + +int main(int argc, char** argv) +{ + try + { + if (argc != 3) + { + cerr << "Usage: " << argv[0] << " input_file tree_file." << endl; + return -1; + } + + ifstream fin(argv[1]); + if (! fin) + { + cerr << "Cannot open data file " << argv[1] << "." << endl; + return -1; + } + + string baseName = argv[2]; + IStorageManager* diskfile = StorageManager::loadDiskStorageManager(baseName); + // this will try to locate and open an already existing storage manager. + + StorageManager::IBuffer* file = StorageManager::createNewRandomEvictionsBuffer(*diskfile, 10, false); + // applies a main memory random buffer on top of the persistent storage manager + // (LRU buffer, etc can be created the same way). + + // If we need to open an existing tree stored in the storage manager, we only + // have to specify the index identifier as follows + ISpatialIndex* tree = TPRTree::loadTPRTree(*file, 1); + + size_t count = 0; + id_type id; + size_t op; + double ax, vx, ay, vy, ct, rt, unused; + double plow[2], phigh[2]; + double pvlow[2], pvhigh[2]; + size_t indexIO = 0; + size_t leafIO = 0; + + while (fin) + { + fin >> id >> op >> ct >> rt >> unused >> ax >> vx >> unused >> ay >> vy; + if (! fin.good()) continue; // skip newlines, etc. + + if (op == INSERT) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(ct, std::numeric_limits<double>::max()); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + //ostringstream os; + //os << r; + //string data = os.str(); + // associate some data with this region. I will use a string that represents the + // region itself, as an example. + // NOTE: It is not necessary to associate any data here. A null pointer can be used. In that + // case you should store the data externally. The index will provide the data IDs of + // the answers to any query, which can be used to access the actual data from the external + // storage (e.g. a hash table or a database table, etc.). + // Storing the data in the index is convinient and in case a clustered storage manager is + // provided (one that stores any node in consecutive pages) performance will improve substantially, + // since disk accesses will be mostly sequential. On the other hand, the index will need to + // manipulate the data, resulting in larger overhead. If you use a main memory storage manager, + // storing the data externally is highly recommended (clustering has no effect). + // A clustered storage manager is NOT provided yet. + // Also you will have to take care of converting you data to and from binary format, since only + // array of bytes can be inserted in the index (see RTree::Node::load and RTree::Node::store for + // an example of how to do that). + + //tree->insertData(data.size() + 1, reinterpret_cast<const byte*>(data.c_str()), r, id); + + tree->insertData(0, 0, r, id); + // example of passing zero size and a null pointer as the associated data. + } + else if (op == DELETE) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = ax; phigh[1] = ay; + pvlow[0] = vx; pvlow[1] = vy; + pvhigh[0] = vx; pvhigh[1] = vy; + Tools::Interval ivT(rt, ct); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + + if (tree->deleteData(r, id) == false) + { + cerr << "******ERROR******" << endl; + cerr << "Cannot delete id: " << id << " , count: " << count << endl; + return -1; + } + } + else if (op == QUERY) + { + plow[0] = ax; plow[1] = ay; + phigh[0] = vx; phigh[1] = vy; + pvlow[0] = 0.0; pvlow[1] = 0.0; + pvhigh[0] = 0.0; pvhigh[1] = 0.0; + + Tools::Interval ivT(ct, rt); + + MovingRegion r = MovingRegion(plow, phigh, pvlow, pvhigh, ivT, 2); + MyVisitor vis; + + tree->intersectsWithQuery(r, vis); + // this will find all data that intersect with the query range. + + indexIO += vis.m_indexIO; + leafIO += vis.m_leafIO; + // example of the Visitor pattern usage, for calculating how many nodes + // were visited. + } + + if ((count % 1000) == 0) + cerr << count << endl; + + count++; + } + + MyQueryStrategy2 qs; + tree->queryStrategy(qs); + + cerr << "Indexed space: " << qs.m_indexedSpace << endl; + cerr << "Operations: " << count << endl; + cerr << *tree; + cerr << "Index I/O: " << indexIO << endl; + cerr << "Leaf I/O: " << leafIO << endl; + cerr << "Buffer hits: " << file->getHits() << endl; + + delete tree; + delete file; + delete diskfile; + // delete the buffer first, then the storage manager + // (otherwise the the buffer will fail writting the dirty entries). + } + catch (Tools::Exception& e) + { + cerr << "******ERROR******" << endl; + std::string s = e.what(); + cerr << s << endl; + return -1; + } + catch (...) + { + cerr << "******ERROR******" << endl; + cerr << "other exception" << endl; + return -1; + } + + return 0; +} diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/all-wcprops new file mode 100644 index 000000000..bd2090d0d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/177/spatialindex/trunk/regressiontest/tprtree/test1 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/tprtree/test1/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/dir-prop-base new file mode 100644 index 000000000..4dbf9b51e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/dir-prop-base @@ -0,0 +1,14 @@ +K 10 +svn:ignore +V 47 +data +queries +.t +b +a +tree.idx +tree.dat +res +res2 + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/entries new file mode 100644 index 000000000..fda6ee83b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/tprtree/test1 +http://svn.gispython.org/spatialindex + + + +2010-03-05T02:56:08.483796Z +177 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.117561Z +72e6ad4acd768c35d10f4c7389374a04 +2007-08-01T20:37:49.786254Z +2 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +640 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/text-base/run.svn-base new file mode 100644 index 000000000..613cd992a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/.svn/text-base/run.svn-base @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator -ds 1000 -sl 100 > d +awk '{if ($2 != 2) print $0}' < d > data +awk '{if ($2 == 2 && $3 >= 100) print $0}' < d > queries +rm -rf d + +echo Creating new TPR-Tree +../TPRTreeLoad data tree 20 + +echo Querying TPR-Tree +../TPRTreeQuery queries tree > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/run new file mode 100755 index 000000000..613cd992a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test1/run @@ -0,0 +1,29 @@ +#! /bin/bash + +echo Generating dataset +../Generator -ds 1000 -sl 100 > d +awk '{if ($2 != 2) print $0}' < d > data +awk '{if ($2 == 2 && $3 >= 100) print $0}' < d > queries +rm -rf d + +echo Creating new TPR-Tree +../TPRTreeLoad data tree 20 + +echo Querying TPR-Tree +../TPRTreeQuery queries tree > res +cat data queries > .t + +echo Running exhaustive search +../Exhaustive .t > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 .t tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/all-wcprops new file mode 100644 index 000000000..a5d2765a1 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/177/spatialindex/trunk/regressiontest/tprtree/test2 +END +run +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/2/spatialindex/trunk/regressiontest/tprtree/test2/run +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/dir-prop-base new file mode 100644 index 000000000..31056d0f6 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/dir-prop-base @@ -0,0 +1,13 @@ +K 10 +svn:ignore +V 36 +mix +a +b +tree.idx +tree.dat +res +res2 + + +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/entries b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/entries new file mode 100644 index 000000000..e5ed11142 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/regressiontest/tprtree/test2 +http://svn.gispython.org/spatialindex + + + +2010-03-05T02:56:08.483796Z +177 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +run +file + + + + +2011-08-01T00:42:34.117561Z +056a30f92ba10da3bc595ac8539caea3 +2007-08-01T20:37:49.786254Z +2 +hobu +has-props + + + + + + + + + + + + + + + + + + + + +471 + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/prop-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/prop-base/run.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/prop-base/run.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/text-base/run.svn-base b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/text-base/run.svn-base new file mode 100644 index 000000000..f13ea2c9a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/.svn/text-base/run.svn-base @@ -0,0 +1,23 @@ +#! /bin/bash + +echo Generating dataset +../Generator -ds 1000 -sl 100 > mix + +echo Creating new TPR-Tree and Querying +../TPRTreeLoad mix tree 10 > res + +echo Running exhaustive search +../Exhaustive mix > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi + diff --git a/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/run b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/run new file mode 100755 index 000000000..f13ea2c9a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/regressiontest/tprtree/test2/run @@ -0,0 +1,23 @@ +#! /bin/bash + +echo Generating dataset +../Generator -ds 1000 -sl 100 > mix + +echo Creating new TPR-Tree and Querying +../TPRTreeLoad mix tree 10 > res + +echo Running exhaustive search +../Exhaustive mix > res2 + +echo Comparing results +sort -n res > a +sort -n res2 > b +if diff a b +then +echo "Same results with exhaustive search. Everything seems fine." +echo Results: `wc -l a` +rm -rf a b res res2 tree.* +else +echo "PROBLEM! We got different results from exhaustive search!" +fi + diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/all-wcprops new file mode 100644 index 000000000..491b0bba4 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 61 +/spatialindex/!svn/ver/131/spatialindex/trunk/spatialindex-vc +END +spatialindex.vcproj +K 25 +svn:wc:ra_dav:version-url +V 81 +/spatialindex/!svn/ver/131/spatialindex/trunk/spatialindex-vc/spatialindex.vcproj +END diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/entries b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/entries new file mode 100644 index 000000000..6ac4ba5b1 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/spatialindex-vc +http://svn.gispython.org/spatialindex + + + +2009-08-13T15:42:43.408031Z +131 +mhadji + + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +spatialindex.vcproj +file + + + + +2011-08-01T00:42:34.901111Z +0e4fff33d029e3291366d1e2752acbce +2009-08-13T15:42:43.408031Z +131 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +21771 + diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/prop-base/spatialindex.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/prop-base/spatialindex.vcproj.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/prop-base/spatialindex.vcproj.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/text-base/spatialindex.vcproj.svn-base b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/text-base/spatialindex.vcproj.svn-base new file mode 100644 index 000000000..42b100f1b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/.svn/text-base/spatialindex.vcproj.svn-base @@ -0,0 +1,960 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="spatialindex-vc"
+ ProjectGUID="{38FBBD59-8344-4D8E-B728-3D51763B6A70}"
+ RootNamespace="spatialindex"
+ Keyword="ManagedCProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex_d.dll"
+ Version="1.5.0"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ AssemblyDebug="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN64;_DEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex64_d.dll"
+ Version="1.5.0"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ AssemblyDebug="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex.dll"
+ Version="1.5.0"
+ LinkIncremental="1"
+ GenerateDebugInformation="false"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN64;NDEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex64.dll"
+ Version="1.5.0"
+ LinkIncremental="1"
+ GenerateDebugInformation="false"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <AssemblyReference
+ RelativePath="System.dll"
+ AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+ />
+ <AssemblyReference
+ RelativePath="System.Data.dll"
+ AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
+ />
+ <AssemblyReference
+ RelativePath="System.XML.dll"
+ AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <Filter
+ Name="mvrtree"
+ >
+ <File
+ RelativePath="..\src\mvrtree\Index.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Index.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Leaf.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Leaf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\MVRTree.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\MVRTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Node.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\PointerPoolNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Statistics.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Statistics.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="rtree"
+ >
+ <File
+ RelativePath="..\src\rtree\BulkLoader.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\BulkLoader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Index.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Index.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Leaf.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Leaf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Node.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\PointerPoolNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\RTree.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\RTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Statistics.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Statistics.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="spatialindex"
+ >
+ <File
+ RelativePath="..\src\spatialindex\LineSegment.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\MovingPoint.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\MovingRegion.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\Point.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\Region.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\SpatialIndexImpl.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\SpatialIndexImpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\TimePoint.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\TimeRegion.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="storagemanager"
+ >
+ <File
+ RelativePath="..\src\storagemanager\Buffer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\Buffer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\DiskStorageManager.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\DiskStorageManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\MemoryStorageManager.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\MemoryStorageManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\RandomEvictionsBuffer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\RandomEvictionsBuffer.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="tools"
+ >
+ <File
+ RelativePath="..\src\tools\rand48.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tools\Tools.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="tprtree"
+ >
+ <File
+ RelativePath="..\src\tprtree\Index.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Index.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Leaf.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Leaf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Node.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\PointerPoolNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Statistics.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Statistics.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\TPRTree.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\TPRTree.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\include\LineSegment.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\MovingPoint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\MovingRegion.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\MVRTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\Point.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\Region.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\RTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\SpatialIndex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\TimePoint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\TimeRegion.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\TPRTree.h"
+ >
+ </File>
+ <Filter
+ Name="tools"
+ >
+ <File
+ RelativePath="..\include\tools\PointerPool.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\PoolPointer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\rand48.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\SmartPointer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\Tools.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/spatialindex.vcproj b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/spatialindex.vcproj new file mode 100755 index 000000000..42b100f1b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex-vc/spatialindex.vcproj @@ -0,0 +1,960 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="spatialindex-vc"
+ ProjectGUID="{38FBBD59-8344-4D8E-B728-3D51763B6A70}"
+ RootNamespace="spatialindex"
+ Keyword="ManagedCProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex_d.dll"
+ Version="1.5.0"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ AssemblyDebug="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN64;_DEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex64_d.dll"
+ Version="1.5.0"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ AssemblyDebug="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex.dll"
+ Version="1.5.0"
+ LinkIncremental="1"
+ GenerateDebugInformation="false"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ ManagedExtensions="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN64;NDEBUG;SPATIALINDEX_CREATE_DLL"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(NoInherit)"
+ OutputFile="$(OutDir)\spatialindex64.dll"
+ Version="1.5.0"
+ LinkIncremental="1"
+ GenerateDebugInformation="false"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <AssemblyReference
+ RelativePath="System.dll"
+ AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+ />
+ <AssemblyReference
+ RelativePath="System.Data.dll"
+ AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
+ />
+ <AssemblyReference
+ RelativePath="System.XML.dll"
+ AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <Filter
+ Name="mvrtree"
+ >
+ <File
+ RelativePath="..\src\mvrtree\Index.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Index.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Leaf.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Leaf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\MVRTree.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\MVRTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Node.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\PointerPoolNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Statistics.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mvrtree\Statistics.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="rtree"
+ >
+ <File
+ RelativePath="..\src\rtree\BulkLoader.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\BulkLoader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Index.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Index.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Leaf.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Leaf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Node.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\PointerPoolNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\RTree.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\RTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\rtree\Statistics.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rtree\Statistics.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="spatialindex"
+ >
+ <File
+ RelativePath="..\src\spatialindex\LineSegment.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\MovingPoint.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\MovingRegion.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\Point.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\Region.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\SpatialIndexImpl.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\SpatialIndexImpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\TimePoint.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\spatialindex\TimeRegion.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="storagemanager"
+ >
+ <File
+ RelativePath="..\src\storagemanager\Buffer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\Buffer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\DiskStorageManager.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\DiskStorageManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\MemoryStorageManager.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\MemoryStorageManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\RandomEvictionsBuffer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\storagemanager\RandomEvictionsBuffer.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="tools"
+ >
+ <File
+ RelativePath="..\src\tools\rand48.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tools\Tools.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="tprtree"
+ >
+ <File
+ RelativePath="..\src\tprtree\Index.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Index.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Leaf.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Leaf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Node.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\PointerPoolNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Statistics.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\tprtree\Statistics.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\TPRTree.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tprtree\TPRTree.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\include\LineSegment.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\MovingPoint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\MovingRegion.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\MVRTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\Point.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\Region.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\RTree.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\SpatialIndex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\TimePoint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\TimeRegion.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\TPRTree.h"
+ >
+ </File>
+ <Filter
+ Name="tools"
+ >
+ <File
+ RelativePath="..\include\tools\PointerPool.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\PoolPointer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\rand48.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\SmartPointer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\tools\Tools.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex.sln b/sci-libs/libspatialindex/svn/trunk/spatialindex.sln new file mode 100755 index 000000000..c0f1d6048 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex.sln @@ -0,0 +1,91 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spatialindex-vc", "spatialindex-vc\spatialindex.vcproj", "{38FBBD59-8344-4D8E-B728-3D51763B6A70}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeBulkLoad", "regressiontest\rtree\RTreeBulkLoad.vcproj", "{7D9C8655-0155-4EE3-B04C-6D831E2982CE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeGenerator", "regressiontest\rtree\RTreeGenerator.vcproj", "{03504DB7-ACF3-40CF-A8A7-310E80666DC0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeLoad", "regressiontest\rtree\RTreeLoad.vcproj", "{551D683C-E5DC-4713-9D9F-F629D15BE5DA}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeQuery", "regressiontest\rtree\RTreeQuery.vcproj", "{1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTreeExhaustive", "regressiontest\rtree\RTreeExhaustive.vcproj", "{D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}"
+ ProjectSection(ProjectDependencies) = postProject
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70} = {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.ActiveCfg = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.Build.0 = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.ActiveCfg = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.Build.0 = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.ActiveCfg = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.Build.0 = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.ActiveCfg = Release|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.Build.0 = Release|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|Win32.Build.0 = Debug|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|x64.ActiveCfg = Debug|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Debug|x64.Build.0 = Debug|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|Win32.ActiveCfg = Release|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|Win32.Build.0 = Release|Win32
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|x64.ActiveCfg = Release|x64
+ {7D9C8655-0155-4EE3-B04C-6D831E2982CE}.Release|x64.Build.0 = Release|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|Win32.Build.0 = Debug|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|x64.ActiveCfg = Debug|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Debug|x64.Build.0 = Debug|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|Win32.ActiveCfg = Release|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|Win32.Build.0 = Release|Win32
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|x64.ActiveCfg = Release|x64
+ {03504DB7-ACF3-40CF-A8A7-310E80666DC0}.Release|x64.Build.0 = Release|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|Win32.Build.0 = Debug|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|x64.ActiveCfg = Debug|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Debug|x64.Build.0 = Debug|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|Win32.ActiveCfg = Release|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|Win32.Build.0 = Release|Win32
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|x64.ActiveCfg = Release|x64
+ {551D683C-E5DC-4713-9D9F-F629D15BE5DA}.Release|x64.Build.0 = Release|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|Win32.Build.0 = Debug|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|x64.ActiveCfg = Debug|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Debug|x64.Build.0 = Debug|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|Win32.ActiveCfg = Release|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|Win32.Build.0 = Release|Win32
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|x64.ActiveCfg = Release|x64
+ {1FBCCD7B-2641-4B93-9CF0-44E1EE8D55B9}.Release|x64.Build.0 = Release|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|Win32.Build.0 = Debug|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|x64.ActiveCfg = Debug|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Debug|x64.Build.0 = Debug|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|Win32.ActiveCfg = Release|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|Win32.Build.0 = Release|Win32
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|x64.ActiveCfg = Release|x64
+ {D2C6947B-5527-4D6A-88CB-842DDCCFB2FF}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/sci-libs/libspatialindex/svn/trunk/spatialindex.suo b/sci-libs/libspatialindex/svn/trunk/spatialindex.suo Binary files differnew file mode 100755 index 000000000..040272d1d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/spatialindex.suo diff --git a/sci-libs/libspatialindex/svn/trunk/src/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/.svn/all-wcprops new file mode 100644 index 000000000..17135f71d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 49 +/spatialindex/!svn/ver/202/spatialindex/trunk/src +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 61 +/spatialindex/!svn/ver/138/spatialindex/trunk/src/Makefile.am +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/.svn/dir-prop-base new file mode 100644 index 000000000..a57f5442b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/.svn/dir-prop-base @@ -0,0 +1,7 @@ +K 10 +svn:ignore +V 21 +Makefile +Makefile.in + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/.svn/entries new file mode 100644 index 000000000..df1617524 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/.svn/entries @@ -0,0 +1,83 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src +http://svn.gispython.org/spatialindex + + + +2011-03-01T14:50:59.673579Z +202 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +storagemanager +dir + +tools +dir + +rtree +dir + +mvrtree +dir + +spatialindex +dir + +tprtree +dir + +Makefile.am +file + + + + +2011-08-01T00:42:34.861109Z +cb96872c0e82412e0c970ff5fa9eaa74 +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +144 + +capi +dir + diff --git a/sci-libs/libspatialindex/svn/trunk/src/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..a5889abfd --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,2 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +SUBDIRS = storagemanager spatialindex rtree mvrtree tprtree tools capi diff --git a/sci-libs/libspatialindex/svn/trunk/src/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/Makefile.am new file mode 100644 index 000000000..a5889abfd --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/Makefile.am @@ -0,0 +1,2 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +SUBDIRS = storagemanager spatialindex rtree mvrtree tprtree tools capi diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/all-wcprops new file mode 100644 index 000000000..ef1a5819f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/all-wcprops @@ -0,0 +1,77 @@ +K 25 +svn:wc:ra_dav:version-url +V 54 +/spatialindex/!svn/ver/198/spatialindex/trunk/src/capi +END +IdVisitor.cc +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/180/spatialindex/trunk/src/capi/IdVisitor.cc +END +LeafQuery.cc +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/172/spatialindex/trunk/src/capi/LeafQuery.cc +END +CustomStorage.cc +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/186/spatialindex/trunk/src/capi/CustomStorage.cc +END +BoundsQuery.cc +K 25 +svn:wc:ra_dav:version-url +V 69 +/spatialindex/!svn/ver/180/spatialindex/trunk/src/capi/BoundsQuery.cc +END +sidx_api.cc +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/198/spatialindex/trunk/src/capi/sidx_api.cc +END +Utility.cc +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/186/spatialindex/trunk/src/capi/Utility.cc +END +DataStream.cc +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/180/spatialindex/trunk/src/capi/DataStream.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/186/spatialindex/trunk/src/capi/Makefile.am +END +Index.cc +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/186/spatialindex/trunk/src/capi/Index.cc +END +CountVisitor.cc +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/180/spatialindex/trunk/src/capi/CountVisitor.cc +END +Error.cc +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/138/spatialindex/trunk/src/capi/Error.cc +END +ObjVisitor.cc +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/180/spatialindex/trunk/src/capi/ObjVisitor.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/dir-prop-base new file mode 100644 index 000000000..0d2dbedbc --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/dir-prop-base @@ -0,0 +1,9 @@ +K 10 +svn:ignore +V 33 +.libs +.deps +Makefile +Makefile.in + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/entries new file mode 100644 index 000000000..d480bc000 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/entries @@ -0,0 +1,436 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/capi +http://svn.gispython.org/spatialindex + + + +2010-11-22T19:53:16.458648Z +198 +seang +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +IdVisitor.cc +file + + + + +2011-08-01T00:42:34.853116Z +d12e408e6df0d373f5cdb4d6fcb81097 +2010-03-31T15:33:43.168720Z +180 +hobu + + + + + + + + + + + + + + + + + + + + + +1619 + +LeafQuery.cc +file + + + + +2011-08-01T00:42:34.853116Z +f6b4eae1e229f385cf64610c582940c1 +2010-03-03T21:55:09.207890Z +172 +hobu + + + + + + + + + + + + + + + + + + + + + +3403 + +CustomStorage.cc +file + + + + +2011-08-01T00:42:34.853116Z +58a25cb12d8b11020f570bcbd8a310a3 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +4069 + +BoundsQuery.cc +file + + + + +2011-08-01T00:42:34.853116Z +d200a112925a958aebb12c6235894c8a +2010-03-31T15:33:43.168720Z +180 +hobu + + + + + + + + + + + + + + + + + + + + + +1618 + +sidx_api.cc +file + + + + +2011-08-01T00:42:34.853116Z +fa077621a77a780cb0e761fbad90bea9 +2010-11-22T19:53:16.458648Z +198 +seang + + + + + + + + + + + + + + + + + + + + + +65363 + +Utility.cc +file + + + + +2011-08-01T00:42:34.853116Z +6b75c01958ed9b9cddca8c66afc00981 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +4379 + +DataStream.cc +file + + + + +2011-08-01T00:42:34.853116Z +709f65e3f1c1a7d5fa9d0f94df6d563d +2010-03-31T15:33:43.168720Z +180 +hobu + + + + + + + + + + + + + + + + + + + + + +2813 + +Makefile.am +file + + + + +2011-08-01T00:42:34.857211Z +2db54e386d4ab8d48bc41a60165804ec +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +399 + +Index.cc +file + + + + +2011-08-01T00:42:34.857211Z +b62ed5931fdca6c78d952c64439d3dc0 +2010-06-19T20:34:19.329614Z +186 +hobu + + + + + + + + + + + + + + + + + + + + + +9970 + +CountVisitor.cc +file + + + + +2011-08-01T00:42:34.857211Z +c1d1818ffc8fb2baacca20078c902795 +2010-03-31T15:33:43.168720Z +180 +hobu + + + + + + + + + + + + + + + + + + + + + +1550 + +Error.cc +file + + + + +2011-08-01T00:42:34.857211Z +a7231de96e05364398b4d1b89c43453b +2009-08-19T16:37:50.582862Z +138 +hobu + + + + + + + + + + + + + + + + + + + + + +1765 + +ObjVisitor.cc +file + + + + +2011-08-01T00:42:34.857211Z +d0a9780a05d2a58f42449ffcc52d40f9 +2010-03-31T15:33:43.168720Z +180 +hobu + + + + + + + + + + + + + + + + + + + + + +1851 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/BoundsQuery.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/BoundsQuery.cc.svn-base new file mode 100644 index 000000000..a7cedb2c4 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/BoundsQuery.cc.svn-base @@ -0,0 +1,45 @@ +/****************************************************************************** + * $Id: boundsquery.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the bounds query. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <capi/sidx_impl.h> + +BoundsQuery::BoundsQuery() +{ + m_bounds = new SpatialIndex::Region; +} + +void BoundsQuery::getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext) +{ + SpatialIndex::IShape* ps; + entry.getShape(&ps); + ps->getMBR(*m_bounds); + delete ps; + + hasNext = false; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/CountVisitor.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/CountVisitor.cc.svn-base new file mode 100644 index 000000000..2fe7e940c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/CountVisitor.cc.svn-base @@ -0,0 +1,52 @@ + +/****************************************************************************** +* $Id$ +* +* Project: libsidx - A C API wrapper around libspatialindex +* Purpose: C++ objects to implement the count visitor. +* Author: Leonard Norrgård, leonard.norrgard@refactor.fi +* +****************************************************************************** +* Copyright (c) 2010, Leonard Norrgård +* +* All rights reserved. +* +* This library is free software; you can redistribute it and/or modify it under +* the terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; either version 2.1 of the License, or (at your option) +* any later version. + +* This library is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +* details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this library; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#include "sidx_impl.h" + +CountVisitor::CountVisitor(): nResults(0) +{ +} + +CountVisitor::~CountVisitor() +{ + +} + +void CountVisitor::visitNode(const SpatialIndex::INode& n) +{ + +} + +void CountVisitor::visitData(const SpatialIndex::IData& d) +{ + nResults += 1; +} + +void CountVisitor::visitData(std::vector<const SpatialIndex::IData*>& v) +{ +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/CustomStorage.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/CustomStorage.cc.svn-base new file mode 100644 index 000000000..e35c00e4d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/CustomStorage.cc.svn-base @@ -0,0 +1,110 @@ +/****************************************************************************** + * $Id: CustomStorage.cc 1385 2009-06-17 13:45:16Z nitro $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the custom storage manager. + * Author: Matthias (nitro) + * + ****************************************************************************** + * Copyright (c) 2010, Matthias (nitro) + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "../spatialindex/SpatialIndexImpl.h" +#include "sidx_impl.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + + +IStorageManager* SpatialIndex::StorageManager::returnCustomStorageManager(Tools::PropertySet& ps) +{ + IStorageManager* sm = new CustomStorageManager(ps); + return sm; +} + +CustomStorageManager::CustomStorageManager(Tools::PropertySet& ps) +{ + Tools::Variant var; + var = ps.getProperty("CustomStorageCallbacks"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PVOID) + throw Tools::IllegalArgumentException("CustomStorageManager: Property CustomStorageCallbacks must be Tools::VT_PVOID"); + + if (!var.m_val.pvVal) + throw Tools::IllegalArgumentException("CustomStorageManager: Property CustomStorageCallbacks must not be 0."); + + // we already checked for validity in IndexProperty_SetCustomStorageCallbacks + CustomStorageManagerCallbacks* callbackArray = static_cast<CustomStorageManagerCallbacks*>(var.m_val.pvVal); + callbacks = *callbackArray; + } + + int errorCode( NoError ); + if ( callbacks.createCallback ) callbacks.createCallback( callbacks.context, &errorCode ); + processErrorCode( errorCode, NewPage ); +} + +CustomStorageManager::~CustomStorageManager() +{ + int errorCode( NoError ); + if ( callbacks.destroyCallback ) callbacks.destroyCallback( callbacks.context, &errorCode ); + processErrorCode( errorCode, NewPage ); +} + +void CustomStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + int errorCode( NoError ); + if ( callbacks.loadByteArrayCallback ) callbacks.loadByteArrayCallback( callbacks.context, page, &len, data, &errorCode ); + processErrorCode( errorCode, page ); +} + +void CustomStorageManager::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + int errorCode( NoError ); + if ( callbacks.storeByteArrayCallback ) callbacks.storeByteArrayCallback( callbacks.context, &page, len, data, &errorCode ); + processErrorCode( errorCode, page ); +} + +void CustomStorageManager::deleteByteArray(const id_type page) +{ + int errorCode( NoError ); + if ( callbacks.deleteByteArrayCallback ) callbacks.deleteByteArrayCallback( callbacks.context, page, &errorCode ); + processErrorCode( errorCode, page ); +} + +inline void CustomStorageManager::processErrorCode(int errorCode, const id_type page) +{ + switch (errorCode) + { + case NoError: + break; + + case InvalidPageError: + throw InvalidPageException( page ); + break; + + case IllegalStateError: + throw Tools::IllegalStateException( "CustomStorageManager: Error in user implementation." ); + break; + + default: + throw Tools::IllegalStateException( "CustomStorageManager: Unknown error." ); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/DataStream.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/DataStream.cc.svn-base new file mode 100644 index 000000000..d30d70ec8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/DataStream.cc.svn-base @@ -0,0 +1,103 @@ +/****************************************************************************** + * $Id: datastream.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the datastream. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + + +DataStream::DataStream(int (*readNext)(SpatialIndex::id_type * id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t** pData, uint32_t *nDataLength)) :m_pNext(0),m_bDoneReading(false) +{ + iterfunct = readNext; + + // Read the first one. + readData(); +} + +DataStream::~DataStream() +{ + if (m_pNext != 0) delete m_pNext; +} + +bool DataStream::readData() +{ + SpatialIndex::id_type id; + double *pMin=0; + double *pMax=0; + uint32_t nDimension=0; + const uint8_t *p_data=0; + uint32_t nDataLength=0; + + if (m_bDoneReading == true) { + return false; + } + + int ret = iterfunct(&id, &pMin, &pMax, &nDimension, &p_data, &nDataLength); + + // The callback should return anything other than 0 + // when it is done. + if (ret != 0) + { + m_bDoneReading = true; + return false; + } + + SpatialIndex::Region r = SpatialIndex::Region(pMin, pMax, nDimension); + m_pNext = new SpatialIndex::RTree::Data(nDataLength, (byte*)p_data, r, id); + + return true; +} + + +SpatialIndex::IData* DataStream::getNext() +{ + if (m_pNext == 0) return 0; + + SpatialIndex::RTree::Data* ret = m_pNext; + m_pNext = 0; + readData(); + return ret; +} + +bool DataStream::hasNext() throw (Tools::NotSupportedException) +{ + return (m_pNext != 0); +} + +uint32_t DataStream::size() throw (Tools::NotSupportedException) +{ + throw Tools::NotSupportedException("Operation not supported."); +} + +void DataStream::rewind() throw (Tools::NotSupportedException) +{ + throw Tools::NotSupportedException("Operation not supported."); + + if (m_pNext != 0) + { + delete m_pNext; + m_pNext = 0; + } +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Error.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Error.cc.svn-base new file mode 100644 index 000000000..19239710b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Error.cc.svn-base @@ -0,0 +1,54 @@ +/****************************************************************************** + * $Id: error.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the error object. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +Error::Error(int code, std::string const& message, std::string const& method) : + m_code(code), + m_message(message), + m_method(method) +{ +} + +Error::Error(Error const& other) : + m_code(other.m_code), + m_message(other.m_message), + m_method(other.m_method) +{ +} + +Error& Error::operator=(Error const& rhs) +{ + if (&rhs != this) + { + m_code = rhs.m_code; + m_message = rhs.m_message; + m_method = rhs.m_method; + + } + return *this; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/IdVisitor.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/IdVisitor.cc.svn-base new file mode 100644 index 000000000..7e0e0b615 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/IdVisitor.cc.svn-base @@ -0,0 +1,53 @@ +/****************************************************************************** + * $Id: idvisitor.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the id visitor. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +IdVisitor::IdVisitor(): nResults(0) +{ +} + +IdVisitor::~IdVisitor() +{ + +} + +void IdVisitor::visitNode(const SpatialIndex::INode& n) +{ + +} + +void IdVisitor::visitData(const SpatialIndex::IData& d) +{ + nResults += 1; + + m_vector.push_back(d.getIdentifier()); +} + +void IdVisitor::visitData(std::vector<const SpatialIndex::IData*>& v) +{ +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Index.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Index.cc.svn-base new file mode 100644 index 000000000..98736043c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Index.cc.svn-base @@ -0,0 +1,381 @@ +/****************************************************************************** + * $Id: index.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the index. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +SpatialIndex::ISpatialIndex* Index::CreateIndex() +{ + using namespace SpatialIndex; + + ISpatialIndex* index = 0; + + Tools::Variant var; + + if (GetIndexType() == RT_RTree) { + + try { + index = RTree::returnRTree( *m_buffer, m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + } + + else if (GetIndexType() == RT_MVRTree) { + + try { + index = MVRTree::returnMVRTree( *m_buffer, m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + } + + else if (GetIndexType() == RT_TPRTree) { + + try { + index = TPRTree::returnTPRTree( *m_buffer,m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + } + + return index; +} + + +Index::Index(const Tools::PropertySet& poProperties) +{ + Setup(); + + m_properties = poProperties; + + Initialize(); +} + + +Index::~Index() +{ + if (m_rtree != 0) + delete m_rtree; + if (m_buffer != 0) + delete m_buffer; + if (m_storage != 0) + delete m_storage; + +} + +Index::Index( const Tools::PropertySet& poProperties, + int (*readNext)(SpatialIndex::id_type *id, + double **pMin, + double **pMax, + uint32_t *nDimension, + const uint8_t **pData, + uint32_t *nDataLength)) +{ + using namespace SpatialIndex; + + Setup(); + + m_properties = poProperties; + + m_storage = CreateStorage(); + m_buffer = CreateIndexBuffer(*m_storage); + + DataStream ds(readNext); + + double dFillFactor = 0.7; + uint32_t nIdxCapacity = 100; + uint32_t nIdxLeafCap = 100; + uint32_t nIdxDimension = 2; + SpatialIndex::RTree::RTreeVariant eVariant = SpatialIndex::RTree::RV_RSTAR; + SpatialIndex::id_type m_IdxIdentifier; + + // Fetch a bunch of properties. We can't bulk load an rtree using merely + // properties, we have to use the helper method(s). + + Tools::Variant var; + var = m_properties.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) + throw std::runtime_error("Index::Index (streaming):" + " Property FillFactor must be Tools::VT_DOUBLE"); + + dFillFactor = var.m_val.dblVal; + } + + var = m_properties.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::Index (streaming): " + "Property IndexCapacity must be Tools::VT_ULONG"); + + nIdxCapacity = var.m_val.ulVal; + } + + var = m_properties.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::Index (streaming): " + "Property LeafCapacity must be Tools::VT_ULONG"); + + nIdxLeafCap = var.m_val.ulVal; + } + + var = m_properties.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::Index (streaming): " + "Property Dimension must be Tools::VT_ULONG"); + + nIdxDimension = var.m_val.ulVal; + } + + var = m_properties.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG) + throw std::runtime_error("Index::Index (streaming): " + "Property TreeVariant must be Tools::VT_LONG"); + + eVariant = static_cast<SpatialIndex::RTree::RTreeVariant>(var.m_val.lVal); + } + + var = m_properties.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONGLONG) + throw std::runtime_error("Index::Index (streaming): " + "Property IndexIdentifier must be Tools::VT_LONGLONG"); + + m_IdxIdentifier = var.m_val.llVal; + } + + m_rtree = RTree::createAndBulkLoadNewRTree( SpatialIndex::RTree::BLM_STR, + ds, + *m_buffer, + dFillFactor, + nIdxCapacity, + nIdxLeafCap, + nIdxDimension, + eVariant, + m_IdxIdentifier); +} + + +SpatialIndex::StorageManager::IBuffer* Index::CreateIndexBuffer(SpatialIndex::IStorageManager& storage) +{ + using namespace SpatialIndex::StorageManager; + IBuffer* buffer = 0; + try { + if ( m_storage == 0 ) + throw std::runtime_error("Storage was invalid to create index buffer"); + buffer = returnRandomEvictionsBuffer(storage, m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + return buffer; +} + + +SpatialIndex::IStorageManager* Index::CreateStorage() +{ + using namespace SpatialIndex::StorageManager; + + SpatialIndex::IStorageManager* storage = 0; + std::string filename(""); + + Tools::Variant var; + var = m_properties.getProperty("FileName"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) + throw std::runtime_error("Index::CreateStorage: " + "Property FileName must be Tools::VT_PCHAR"); + + filename = std::string(var.m_val.pcVal); + } + + if (GetIndexStorage() == RT_Disk) { + if (filename.empty()) { + std::ostringstream os; + os << "Spatial Index Error: filename was empty." + " Set IndexStorageType to RT_Memory"; + throw std::runtime_error(os.str()); + } + try { + storage = returnDiskStorageManager(m_properties); + return storage; + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + + } else if (GetIndexStorage() == RT_Memory) { + + try { + storage = returnMemoryStorageManager(m_properties); + return storage; + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + + } else if (GetIndexStorage() == RT_Custom) { + + try { + storage = returnCustomStorageManager(m_properties); + return storage; + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + + } + return storage; +} + + + + +void Index::Initialize() +{ + m_storage = CreateStorage(); + m_buffer = CreateIndexBuffer(*m_storage); + m_rtree = CreateIndex(); +} + +void Index::Setup() + +{ + m_buffer = 0; + m_storage = 0; + m_rtree = 0; +} + +RTIndexType Index::GetIndexType() +{ + Tools::Variant var; + var = m_properties.getProperty("IndexType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::GetIndexType: " + "Property IndexType must be Tools::VT_ULONG"); + + return static_cast<RTIndexType>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + return RT_InvalidIndexType; + +} +void Index::SetIndexType(RTIndexType v) +{ + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = v; + m_properties.setProperty("IndexType", var); +} + +RTStorageType Index::GetIndexStorage() +{ + + Tools::Variant var; + var = m_properties.getProperty("IndexStorageType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::GetIndexStorage: " + "Property IndexStorageType must be Tools::VT_ULONG"); + + return static_cast<RTStorageType>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + return RT_InvalidStorageType; +} + +void Index::SetIndexStorage(RTStorageType v) +{ + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = v; + m_properties.setProperty("IndexStorageType", var); +} + +RTIndexVariant Index::GetIndexVariant() +{ + + Tools::Variant var; + var = m_properties.getProperty("TreeVariant"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::GetIndexVariant: " + "Property TreeVariant must be Tools::VT_ULONG"); + + return static_cast<RTIndexVariant>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + return RT_InvalidIndexVariant; +} + +void Index::SetIndexVariant(RTStorageType v) +{ + using namespace SpatialIndex; + Tools::Variant var; + + if (GetIndexType() == RT_RTree) { + var.m_val.ulVal = static_cast<RTree::RTreeVariant>(v); + m_properties.setProperty("TreeVariant", var); + } else if (GetIndexType() == RT_MVRTree) { + var.m_val.ulVal = static_cast<MVRTree::MVRTreeVariant>(v); + m_properties.setProperty("TreeVariant", var); + } else if (GetIndexType() == RT_TPRTree) { + var.m_val.ulVal = static_cast<TPRTree::TPRTreeVariant>(v); + m_properties.setProperty("TreeVariant", var); + } +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/LeafQuery.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/LeafQuery.cc.svn-base new file mode 100644 index 000000000..0d0998278 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/LeafQuery.cc.svn-base @@ -0,0 +1,126 @@ +/****************************************************************************** + * $Id: boundsquery.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement a query of the index's leaves. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <capi/sidx_impl.h> + +LeafQuery::LeafQuery() +{ + +} + +LeafQueryResult get_results(const SpatialIndex::INode* n) +{ + LeafQueryResult result (n->getIdentifier()); + + SpatialIndex::IShape* ps; + n->getShape(&ps); + SpatialIndex::Region* pr = dynamic_cast<SpatialIndex::Region*>(ps); + std::vector<SpatialIndex::id_type> ids; + for (size_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push_back(n->getChildIdentifier(cChild)); + } + + result.SetIDs(ids); + result.SetBounds(pr); + delete ps; + + return result; +} +void LeafQuery::getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext) +{ + + const SpatialIndex::INode* n = dynamic_cast<const SpatialIndex::INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 0) + { + for (uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + m_ids.push(n->getChildIdentifier(cChild)); + } + } + + if (n->isLeaf()) { + m_results.push_back(get_results(n)); + } + + if (! m_ids.empty()) + { + nextEntry = m_ids.front(); m_ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } +} + + +std::vector<SpatialIndex::id_type> const& LeafQueryResult::GetIDs() const +{ + return ids; +} + +void LeafQueryResult::SetIDs(std::vector<SpatialIndex::id_type>& v) +{ + ids.resize(v.size()); + std::copy(v.begin(), v.end(), ids.begin()); +} +const SpatialIndex::Region* LeafQueryResult::GetBounds() const +{ + return bounds; +} + +void LeafQueryResult::SetBounds(const SpatialIndex::Region* b) +{ + bounds = new SpatialIndex::Region(*b); +} + +LeafQueryResult::LeafQueryResult(LeafQueryResult const& other) +{ + ids.resize(other.ids.size()); + std::copy(other.ids.begin(), other.ids.end(), ids.begin()); + m_id = other.m_id; + + bounds = other.bounds->clone(); +} + +LeafQueryResult& LeafQueryResult::operator=(LeafQueryResult const& rhs) +{ + if (&rhs != this) + { + ids.resize(rhs.ids.size()); + std::copy(rhs.ids.begin(), rhs.ids.end(), ids.begin()); + m_id = rhs.m_id; + bounds = rhs.bounds->clone(); + } + return *this; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..2c35d4002 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,14 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libsidxc.la +INCLUDES = -I../../include -I../../include/capi +libsidxc_la_SOURCES = BoundsQuery.cc \ + CountVisitor.cc \ + CustomStorage.cc \ + DataStream.cc \ + Error.cc \ + IdVisitor.cc \ + Index.cc \ + LeafQuery.cc \ + ObjVisitor.cc \ + sidx_api.cc \ + Utility.cc diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/ObjVisitor.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/ObjVisitor.cc.svn-base new file mode 100644 index 000000000..436f7b9a9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/ObjVisitor.cc.svn-base @@ -0,0 +1,60 @@ +/****************************************************************************** + * $Id: objvisitor.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +ObjVisitor::ObjVisitor(): nResults(0) +{ +} + +ObjVisitor::~ObjVisitor() +{ + std::vector<SpatialIndex::IData*>::iterator it; + for (it = m_vector.begin(); it != m_vector.end(); it++) { + delete *it; + } + +} + +void ObjVisitor::visitNode(const SpatialIndex::INode& n) +{ +} + +void ObjVisitor::visitData(const SpatialIndex::IData& d) +{ + + SpatialIndex::IData* item = dynamic_cast<SpatialIndex::IData*>(const_cast<SpatialIndex::IData&>(d).clone()) ; + + nResults += 1; + + m_vector.push_back(item); +} + +void ObjVisitor::visitData(std::vector<const SpatialIndex::IData*>& v) +{ +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Utility.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Utility.cc.svn-base new file mode 100644 index 000000000..e441853c3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/Utility.cc.svn-base @@ -0,0 +1,150 @@ +/****************************************************************************** + * $Id: util.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement utilities. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +Tools::PropertySet* GetDefaults() +{ + Tools::PropertySet* ps = new Tools::PropertySet; + + Tools::Variant var; + + // Rtree defaults + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 0.7; + ps->setProperty("FillFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = SpatialIndex::RTree::RV_RSTAR; + ps->setProperty("TreeVariant", var); + + // var.m_varType = Tools::VT_LONGLONG; + // var.m_val.llVal = 0; + // ps->setProperty("IndexIdentifier", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 32; + ps->setProperty("NearMinimumOverlapFactor", var); + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 0.4; + ps->setProperty("SplitDistributionFactor", var); + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 0.3; + ps->setProperty("ReinsertFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 2; + ps->setProperty("Dimension", var); + + var.m_varType = Tools::VT_BOOL; + var.m_val.bVal = true; + ps->setProperty("EnsureTightMBRs", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("IndexPoolCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("LeafPoolCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 1000; + ps->setProperty("RegionPoolCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 500; + ps->setProperty("PointPoolCapacity", var); + + // horizon for TPRTree + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 20.0; + ps->setProperty("Horizon", var); + + // Buffering defaults + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 10; + ps->setProperty("Capacity", var); + + var.m_varType = Tools::VT_BOOL; + var.m_val.bVal = false; + ps->setProperty("WriteThrough", var); + + // Disk Storage Manager defaults + var.m_varType = Tools::VT_BOOL; + var.m_val.bVal = true; + ps->setProperty("Overwrite", var); + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>(""); + ps->setProperty("FileName", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 4096; + ps->setProperty("PageSize", var); + + // Our custom properties related to whether + // or not we are using a disk or memory storage manager + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = RT_Disk; + ps->setProperty("IndexStorageType", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = RT_RTree; + ps->setProperty("IndexType", var); + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>("dat"); + ps->setProperty("FileNameDat", var); + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>("idx"); + ps->setProperty("FileNameIdx", var); + + // Custom storage manager properties + var.m_varType = Tools::VT_ULONG; + var.m_val.pcVal = 0; + ps->setProperty("CustomStorageCallbacksSize", var); + + var.m_varType = Tools::VT_PVOID; + var.m_val.pcVal = 0; + ps->setProperty("CustomStorageCallbacks", var); + + return ps; +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/sidx_api.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/sidx_api.cc.svn-base new file mode 100644 index 000000000..e2b24c98f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/.svn/text-base/sidx_api.cc.svn-base @@ -0,0 +1,2518 @@ +/****************************************************************************** + * $Id: sidx_api.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C API wrapper implementation + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <cmath> +#include <limits> +#include "sidx_impl.h" + +static std::stack<Error> errors; + +#define VALIDATE_POINTER0(ptr, func) \ + do { if( NULL == ptr ) { \ + RTError const ret = RT_Failure; \ + std::ostringstream msg; \ + msg << "Pointer \'" << #ptr << "\' is NULL in \'" << (func) <<"\'."; \ + std::string message(msg.str()); \ + Error_PushError( ret, message.c_str(), (func)); \ + return; \ + }} while(0) + +#define VALIDATE_POINTER1(ptr, func, rc) \ + do { if( NULL == ptr ) { \ + RTError const ret = RT_Failure; \ + std::ostringstream msg; \ + msg << "Pointer \'" << #ptr << "\' is NULL in \'" << (func) <<"\'."; \ + std::string message(msg.str()); \ + Error_PushError( ret, message.c_str(), (func)); \ + return (rc); \ + }} while(0) + +IDX_C_START + +SIDX_C_DLL void Error_Reset(void) { + if (errors.empty()) return; + for (std::size_t i=0;i<errors.size();i++) errors.pop(); +} + +SIDX_C_DLL void Error_Pop(void) { + if (errors.empty()) return; + errors.pop(); +} + +SIDX_C_DLL int Error_GetLastErrorNum(void){ + if (errors.empty()) + return 0; + else { + Error err = errors.top(); + return err.GetCode(); + } +} + +SIDX_C_DLL char* Error_GetLastErrorMsg(void){ + if (errors.empty()) + return NULL; + else { + Error err = errors.top(); + return STRDUP(err.GetMessage()); + } +} + +SIDX_C_DLL char* Error_GetLastErrorMethod(void){ + if (errors.empty()) + return NULL; + else { + Error err = errors.top(); + return STRDUP(err.GetMethod()); + } +} + +SIDX_C_DLL void Error_PushError(int code, const char *message, const char *method) { + Error err = Error(code, std::string(message), std::string(method)); + errors.push(err); +} + +SIDX_C_DLL int Error_GetErrorCount(void) { + return static_cast<int>(errors.size()); +} + +SIDX_C_DLL IndexH Index_Create(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "Index_Create", NULL); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try { + return (IndexH) new Index(*prop); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Create"); + return NULL; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Create"); + return NULL; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Create"); + return NULL; + } + return NULL; +} + +SIDX_C_DLL IndexH Index_CreateWithStream( IndexPropertyH hProp, + int (*readNext)(SpatialIndex::id_type *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength) + ) +{ + VALIDATE_POINTER1(hProp, "Index_CreateWithStream", NULL); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + + try { + return (IndexH) new Index(*prop, readNext); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_CreateWithStream"); + return NULL; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_CreateWithStream"); + return NULL; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_CreateWithStream"); + return NULL; + } + return NULL; +} + +SIDX_C_DLL void Index_Destroy(IndexH index) +{ + VALIDATE_POINTER0(index, "Index_Destroy"); + Index* idx = (Index*) index; + if (idx) delete idx; +} + +SIDX_C_DLL RTError Index_DeleteData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension) +{ + VALIDATE_POINTER1(index, "Index_DeleteData", RT_Failure); + + Index* idx = static_cast<Index*>(index); + + try { + idx->index().deleteData(SpatialIndex::Region(pdMin, pdMax, nDimension), id); + return RT_None; + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_DeleteData"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_DeleteData"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_DeleteData"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_InsertData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension, + const uint8_t* pData, + uint32_t nDataLength) +{ + VALIDATE_POINTER1(index, "Index_InsertData", RT_Failure); + + Index* idx = static_cast<Index*>(index); + + // Test the data and check for the case when minx == maxx, miny == maxy + // and minz == maxz. In that case, we will insert a SpatialIndex::Point + // instead of a SpatialIndex::Region + + bool isPoint = false; + SpatialIndex::IShape* shape = 0; + double const epsilon = std::numeric_limits<double>::epsilon(); + + double length(0); + for (uint32_t i = 0; i < nDimension; ++i) { + double delta = pdMin[i] - pdMax[i]; + length += std::fabs(delta); + } + + if (length <= epsilon) { + isPoint = true; + } + + if (isPoint == true) { + shape = new SpatialIndex::Point(pdMin, nDimension); + } else { + shape = new SpatialIndex::Region(pdMin, pdMax, nDimension); + } + try { + idx->index().insertData(nDataLength, + pData, + *shape, + id); + + delete shape; + return RT_None; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_InsertData"); + delete shape; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_InsertData"); + delete shape; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_InsertData"); + delete shape; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_Intersects_obj( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_Intersects_obj", RT_Failure); + Index* idx = static_cast<Index*>(index); + + ObjVisitor* visitor = new ObjVisitor; + try { + SpatialIndex::Region* r = new SpatialIndex::Region(pdMin, pdMax, nDimension); + idx->index().intersectsWithQuery( *r, + *visitor); + + *items = (SpatialIndex::IData**) malloc (visitor->GetResultCount() * sizeof(SpatialIndex::IData*)); + + std::vector<SpatialIndex::IData*>& results = visitor->GetResults(); + + // copy the Items into the newly allocated item array + // we need to make sure to copy the actual Item instead + // of just the pointers, as the visitor will nuke them + // upon ~ + for (uint32_t i=0; i < visitor->GetResultCount(); ++i) + { + SpatialIndex::IData* result =results[i]; + (*items)[i] = dynamic_cast<SpatialIndex::IData*>(result->clone()); + + } + *nResults = visitor->GetResultCount(); + + delete r; + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Intersects_obj"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Intersects_obj"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Intersects_obj"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_Intersects_id( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** ids, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_Intersects_id", RT_Failure); + Index* idx = static_cast<Index*>(index); + + IdVisitor* visitor = new IdVisitor; + try { + SpatialIndex::Region* r = new SpatialIndex::Region(pdMin, pdMax, nDimension); + idx->index().intersectsWithQuery( *r, + *visitor); + + *nResults = visitor->GetResultCount(); + + *ids = (uint64_t*) malloc (*nResults * sizeof(uint64_t)); + + std::vector<uint64_t>& results = visitor->GetResults(); + + for (uint32_t i=0; i < *nResults; ++i) + { + (*ids)[i] = results[i]; + + } + + delete r; + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Intersects_id"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Intersects_id"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Intersects_id"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_Intersects_count( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_Intersects_count", RT_Failure); + Index* idx = static_cast<Index*>(index); + + CountVisitor* visitor = new CountVisitor; + try { + SpatialIndex::Region* r = new SpatialIndex::Region(pdMin, pdMax, nDimension); + idx->index().intersectsWithQuery( *r, + *visitor); + + *nResults = visitor->GetResultCount(); + + delete r; + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Intersects_count"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Intersects_count"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Intersects_count"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_NearestNeighbors_id(IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** ids, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_NearestNeighbors_id", RT_Failure); + Index* idx = static_cast<Index*>(index); + + IdVisitor* visitor = new IdVisitor; + + try { + idx->index().nearestNeighborQuery( *nResults, + SpatialIndex::Region(pdMin, pdMax, nDimension), + *visitor); + + *ids = (uint64_t*) malloc (visitor->GetResultCount() * sizeof(uint64_t)); + + std::vector<uint64_t>& results = visitor->GetResults(); + + *nResults = results.size(); + + for (uint32_t i=0; i < *nResults; ++i) + { + (*ids)[i] = results[i]; + + } + + + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_NearestNeighbors_id"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_NearestNeighbors_id"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_NearestNeighbors_id"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_NearestNeighbors_obj(IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_NearestNeighbors_obj", RT_Failure); + Index* idx = static_cast<Index*>(index); + + ObjVisitor* visitor = new ObjVisitor; + try { + idx->index().nearestNeighborQuery( *nResults, + SpatialIndex::Region(pdMin, pdMax, nDimension), + *visitor); + + + *items = (SpatialIndex::IData**) malloc (visitor->GetResultCount() * sizeof(Item*)); + + std::vector<SpatialIndex::IData*> results = visitor->GetResults(); + *nResults = results.size(); + + // copy the Items into the newly allocated item array + // we need to make sure to copy the actual Item instead + // of just the pointers, as the visitor will nuke them + // upon ~ + for (uint32_t i=0; i < visitor->GetResultCount(); ++i) + { + SpatialIndex::IData* result = results[i]; + (*items)[i] = dynamic_cast<SpatialIndex::IData*>(result->clone()); + + } + + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_NearestNeighbors_obj"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_NearestNeighbors_obj"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_NearestNeighbors_obj"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_GetBounds( IndexH index, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension) +{ + VALIDATE_POINTER1(index, "Index_GetBounds", RT_Failure); + Index* idx = static_cast<Index*>(index); + + BoundsQuery* query = new BoundsQuery; + + try { + idx->index().queryStrategy( *query); + + const SpatialIndex::Region* bounds = query->GetBounds(); + if (bounds == 0) { + *nDimension = 0; + delete query; + return RT_None; + } + + *nDimension =bounds->getDimension(); + + *ppdMin = (double*) malloc (*nDimension * sizeof(double)); + *ppdMax = (double*) malloc (*nDimension * sizeof(double)); + + for (uint32_t i=0; i< *nDimension; ++i) { + (*ppdMin)[i] = bounds->getLow(i); + (*ppdMax)[i] = bounds->getHigh(i); + } + + delete query; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_GetBounds"); + delete query; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_GetBounds"); + delete query; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_GetBounds"); + delete query; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t Index_IsValid(IndexH index) +{ + VALIDATE_POINTER1(index, "Index_IsValid", 0); + Index* idx = static_cast<Index*>(index); + return static_cast<uint32_t>(idx->index().isIndexValid()); +} + +SIDX_C_DLL IndexPropertyH Index_GetProperties(IndexH index) +{ + VALIDATE_POINTER1(index, "Index_GetProperties", 0); + Index* idx = static_cast<Index*>(index); + Tools::PropertySet* ps = new Tools::PropertySet; + + idx->index().getIndexProperties(*ps); + return (IndexPropertyH)ps; +} + +SIDX_C_DLL IndexPropertyH Index_ClearBuffer(IndexH index) +{ + VALIDATE_POINTER1(index, "Index_ClearBuffer", 0); + Index* idx = static_cast<Index*>(index); + idx->buffer().clear(); +} + +SIDX_C_DLL void Index_DestroyObjResults(IndexItemH* results, uint32_t nResults) +{ + VALIDATE_POINTER0(results, "Index_DestroyObjResults"); + SpatialIndex::IData* it; + for (uint32_t i=0; i< nResults; ++i) { + if (results[i] != NULL) { + it = static_cast<SpatialIndex::IData*>(results[i]); + if (it != 0) + delete it; + } + } + + std::free(results); +} + + +SIDX_C_DLL void Index_Free(void* results) +{ + VALIDATE_POINTER0(results, "Index_Free"); + if (results != 0) + std::free(results); +} + +SIDX_C_DLL RTError Index_GetLeaves( IndexH index, + uint32_t* nNumLeafNodes, + uint32_t** nLeafSizes, + int64_t** nLeafIDs, + int64_t*** nLeafChildIDs, + double*** pppdMin, + double*** pppdMax, + uint32_t* nDimension) +{ + VALIDATE_POINTER1(index, "Index_GetLeaves", RT_Failure); + Index* idx = static_cast<Index*>(index); + + std::vector<LeafQueryResult>::const_iterator i; + LeafQuery* query = new LeafQuery; + + // Fetch the dimensionality of the index + Tools::PropertySet ps; + idx->index().getIndexProperties(ps); + + Tools::Variant var; + var = ps.getProperty("Dimension"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property Dimension must be Tools::VT_ULONG", + "Index_GetLeaves"); + return RT_Failure; + } + } + + *nDimension = var.m_val.ulVal; + + try { + idx->index().queryStrategy( *query); + + const std::vector<LeafQueryResult>& results = query->GetResults(); + + *nNumLeafNodes = results.size(); + + *nLeafSizes = (uint32_t*) malloc (*nNumLeafNodes * sizeof(uint32_t)); + *nLeafIDs = (int64_t*) malloc (*nNumLeafNodes * sizeof(int64_t)); + + *nLeafChildIDs = (int64_t**) malloc(*nNumLeafNodes * sizeof(int64_t*)); + *pppdMin = (double**) malloc (*nNumLeafNodes * sizeof(double*)); + *pppdMax = (double**) malloc (*nNumLeafNodes * sizeof(double*)); + + uint32_t k=0; + for (i = results.begin(); i != results.end(); ++i) + { + std::vector<SpatialIndex::id_type> const& ids = (*i).GetIDs(); + const SpatialIndex::Region* b = (*i).GetBounds(); + + (*nLeafIDs)[k] = (*i).getIdentifier(); + (*nLeafSizes)[k] = ids.size(); + + (*nLeafChildIDs)[k] = (int64_t*) malloc( (*nLeafSizes)[k] * sizeof(int64_t)); + (*pppdMin)[k] = (double*) malloc ( (*nLeafSizes)[k] * sizeof(double)); + (*pppdMax)[k] = (double*) malloc ( (*nLeafSizes)[k] * sizeof(double)); + for (uint32_t i=0; i< *nDimension; ++i) { + (*pppdMin)[k][i] = b->getLow(i); + (*pppdMax)[k][i] = b->getHigh(i); + } + for (uint32_t cChild = 0; cChild < ids.size(); cChild++) + { + (*nLeafChildIDs)[k][cChild] = ids[cChild]; + } + ++k; + } + + + delete query; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_GetLeaves"); + delete query; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_GetLeaves"); + delete query; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_GetLeaves"); + delete query; + return RT_Failure; + } + return RT_None; +} + + +SIDX_C_DLL void IndexItem_Destroy(IndexItemH item) +{ + VALIDATE_POINTER0(item, "IndexItem_Destroy"); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + if (it != 0) delete it; +} + +SIDX_C_DLL RTError IndexItem_GetData( IndexItemH item, + uint8_t** data, + uint64_t* length) +{ + VALIDATE_POINTER1(item, "IndexItem_GetData", RT_Failure); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + uint8_t* p_data; + uint32_t* l= new uint32_t; + + it->getData(*l,&p_data); + *length = (uint64_t)*l; + *data = (uint8_t*) malloc (*length * sizeof(uint8_t)); + + memcpy(*data, p_data, *length); + delete[] p_data; + delete l; + return RT_None; + +} + +SIDX_C_DLL uint64_t IndexItem_GetID(IndexItemH item) +{ + VALIDATE_POINTER1(item, "IndexItem_GetID",0); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + uint64_t value = it->getIdentifier(); + return value; +} + +SIDX_C_DLL RTError IndexItem_GetBounds( IndexItemH item, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension) +{ + VALIDATE_POINTER1(item, "IndexItem_GetBounds", RT_Failure); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + + SpatialIndex::IShape* s; + it->getShape(&s); + + SpatialIndex::Region *bounds = new SpatialIndex::Region(); + s->getMBR(*bounds); + + if (bounds == 0) { + *nDimension = 0; + delete bounds; + delete s; + return RT_None; + } + *nDimension = bounds->getDimension(); + + *ppdMin = (double*) malloc (*nDimension * sizeof(double)); + *ppdMax = (double*) malloc (*nDimension * sizeof(double)); + + if (ppdMin == NULL || ppdMax == NULL) { + Error_PushError(RT_Failure, + "Unable to allocation bounds array(s)", + "IndexItem_GetBounds"); + return RT_Failure; + } + + for (uint32_t i=0; i< *nDimension; ++i) { + (*ppdMin)[i] = bounds->getLow(i); + (*ppdMax)[i] = bounds->getHigh(i); + } + delete bounds; + delete s; + return RT_None; +} +SIDX_C_DLL IndexPropertyH IndexProperty_Create() +{ + Tools::PropertySet* ps = GetDefaults(); + Tools::Variant var; + return (IndexPropertyH)ps; +} + +SIDX_C_DLL void IndexProperty_Destroy(IndexPropertyH hProp) +{ + VALIDATE_POINTER0(hProp, "IndexProperty_Destroy"); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + if (prop != 0) delete prop; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexType(IndexPropertyH hProp, + RTIndexType value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexType", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (!(value == RT_RTree || value == RT_MVRTree || value == RT_TPRTree)) { + throw std::runtime_error("Inputted value is not a valid index type"); + } + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexType", var); + + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexType"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexType"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexType"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTIndexType IndexProperty_GetIndexType(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexType", RT_InvalidIndexType); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexType must be Tools::VT_ULONG", + "IndexProperty_GetIndexType"); + return RT_InvalidIndexType; + } + return (RTIndexType) var.m_val.ulVal; + } + + Error_PushError(RT_Failure, + "Property IndexType was empty", + "IndexProperty_GetIndexType"); + return RT_InvalidIndexType; + +} + +SIDX_C_DLL RTError IndexProperty_SetDimension(IndexPropertyH hProp, uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetDimension", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("Dimension", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetDimension"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetDimension"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetDimension"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetDimension(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetDimension", RT_InvalidIndexType); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Dimension"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexType must be Tools::VT_ULONG", + "IndexProperty_GetDimension"); + return 0; + } + + return var.m_val.ulVal; + } + + // A zero dimension index is invalid. + Error_PushError(RT_Failure, + "Property Dimension was empty", + "IndexProperty_GetDimension"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexVariant( IndexPropertyH hProp, + RTIndexVariant value) +{ + using namespace SpatialIndex; + + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexVariant", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + + try + { + + if (!(value == RT_Linear || value == RT_Quadratic || value == RT_Star)) { + throw std::runtime_error("Inputted value is not a valid index variant"); + } + + var.m_varType = Tools::VT_LONG; + RTIndexType type = IndexProperty_GetIndexType(hProp); + if (type == RT_InvalidIndexType ) { + Error_PushError(RT_Failure, + "Index type is not properly set", + "IndexProperty_SetIndexVariant"); + return RT_Failure; + } + if (type == RT_RTree) { + var.m_val.lVal = static_cast<RTree::RTreeVariant>(value); + prop->setProperty("TreeVariant", var); + } else if (type == RT_MVRTree) { + var.m_val.lVal = static_cast<MVRTree::MVRTreeVariant>(value); + prop->setProperty("TreeVariant", var); + } else if (type == RT_TPRTree) { + var.m_val.lVal = static_cast<TPRTree::TPRTreeVariant>(value); + prop->setProperty("TreeVariant", var); + } + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexVariant"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTIndexVariant IndexProperty_GetIndexVariant(IndexPropertyH hProp) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_GetIndexVariant", + RT_InvalidIndexVariant); + + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("TreeVariant"); + + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG) { + Error_PushError(RT_Failure, + "Property IndexVariant must be Tools::VT_LONG", + "IndexProperty_GetIndexVariant"); + return RT_InvalidIndexVariant; + } + + return static_cast<RTIndexVariant>(var.m_val.lVal); + } + + // if we didn't get anything, we're returning an error condition + Error_PushError(RT_Failure, + "Property IndexVariant was empty", + "IndexProperty_GetIndexVariant"); + return RT_InvalidIndexVariant; + +} + +SIDX_C_DLL RTError IndexProperty_SetIndexStorage( IndexPropertyH hProp, + RTStorageType value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexStorage", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (!(value == RT_Disk || value == RT_Memory || value == RT_Custom)) { + throw std::runtime_error("Inputted value is not a valid index storage type"); + } + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexStorageType", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexStorage"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexStorage"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexStorage"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTStorageType IndexProperty_GetIndexStorage(IndexPropertyH hProp) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_GetIndexStorage", + RT_InvalidStorageType); + + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexStorageType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexStorage must be Tools::VT_ULONG", + "IndexProperty_GetIndexStorage"); + return RT_InvalidStorageType; + } + + return static_cast<RTStorageType>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + Error_PushError(RT_Failure, + "Property IndexStorage was empty", + "IndexProperty_GetIndexStorage"); + return RT_InvalidStorageType; + +} + +SIDX_C_DLL RTError IndexProperty_SetIndexCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetIndexCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexCapacity must be Tools::VT_ULONG", + "IndexProperty_GetIndexCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property IndexCapacity was empty", + "IndexProperty_GetIndexCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetLeafCapacity( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetLeafCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("LeafCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetLeafCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetLeafCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetLeafCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetLeafCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetLeafCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("LeafCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property LeafCapacity must be Tools::VT_ULONG", + "IndexProperty_GetLeafCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property LeafCapacity was empty", + "IndexProperty_GetLeafCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetPagesize( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetPagesize", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("PageSize", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetPagesize"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetPagesize"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetPagesize"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetPagesize(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetPagesize", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("PageSize"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property PageSize must be Tools::VT_ULONG", + "IndexProperty_GetPagesize"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property PageSize was empty", + "IndexProperty_GetPagesize"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetLeafPoolCapacity( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetLeafPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("LeafPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetLeafPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetLeafPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetLeafPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetLeafPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetLeafPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("LeafPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property LeafPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetLeafPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property LeafPoolCapacity was empty", + "IndexProperty_GetLeafPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexPoolCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetIndexPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetIndexPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property IndexPoolCapacity was empty", + "IndexProperty_GetIndexPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetRegionPoolCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetRegionPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("RegionPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetRegionPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetRegionPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetRegionPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetRegionPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetRegionPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("RegionPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property RegionPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetRegionPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property RegionPoolCapacity was empty", + "IndexProperty_GetRegionPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetPointPoolCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetPointPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("PointPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetPointPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetPointPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetPointPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetPointPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetPointPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("PointPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property PointPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetPointPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property PointPoolCapacity was empty", + "IndexProperty_GetPointPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetNearMinimumOverlapFactor( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetNearMinimumOverlapFactor", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("NearMinimumOverlapFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetNearMinimumOverlapFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetNearMinimumOverlapFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetNearMinimumOverlapFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetNearMinimumOverlapFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetNearMinimumOverlapFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("NearMinimumOverlapFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property NearMinimumOverlapFactor must be Tools::VT_ULONG", + "IndexProperty_GetNearMinimumOverlapFactor"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property NearMinimumOverlapFactor was empty", + "IndexProperty_GetNearMinimumOverlapFactor"); + return 0; +} + + +SIDX_C_DLL RTError IndexProperty_SetBufferingCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetBufferingCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("Capacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetBufferingCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetBufferingCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetBufferingCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetBufferingCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetBufferingCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Capacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property Capacity must be Tools::VT_ULONG", + "IndexProperty_GetBufferingCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property Capacity was empty", + "IndexProperty_GetBufferingCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetEnsureTightMBRs( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetEnsureTightMBRs", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (value > 1 ) { + Error_PushError(RT_Failure, + "EnsureTightMBRs is a boolean value and must be 1 or 0", + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } + Tools::Variant var; + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = (bool)value; + prop->setProperty("EnsureTightMBRs", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetEnsureTightMBRs(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetEnsureTightMBRs", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("EnsureTightMBRs"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) { + Error_PushError(RT_Failure, + "Property EnsureTightMBRs must be Tools::VT_BOOL", + "IndexProperty_GetEnsureTightMBRs"); + return 0; + } + + return var.m_val.blVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property EnsureTightMBRs was empty", + "IndexProperty_GetEnsureTightMBRs"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetWriteThrough(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetWriteThrough", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (value > 1 ) { + Error_PushError(RT_Failure, + "WriteThrough is a boolean value and must be 1 or 0", + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } + Tools::Variant var; + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = value; + prop->setProperty("WriteThrough", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetWriteThrough(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetWriteThrough", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("WriteThrough"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) { + Error_PushError(RT_Failure, + "Property WriteThrough must be Tools::VT_BOOL", + "IndexProperty_GetWriteThrough"); + return 0; + } + + return var.m_val.blVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property WriteThrough was empty", + "IndexProperty_GetWriteThrough"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetOverwrite(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetOverwrite", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (value > 1 ) { + Error_PushError(RT_Failure, + "Overwrite is a boolean value and must be 1 or 0", + "IndexProperty_SetOverwrite"); + return RT_Failure; + } + Tools::Variant var; + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = value; + prop->setProperty("Overwrite", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetOverwrite"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetOverwrite"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetOverwrite"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetOverwrite(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetOverwrite", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Overwrite"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) { + Error_PushError(RT_Failure, + "Property Overwrite must be Tools::VT_BOOL", + "IndexProperty_GetOverwrite"); + return 0; + } + + return var.m_val.blVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property Overwrite was empty", + "IndexProperty_GetOverwrite"); + return 0; +} + + +SIDX_C_DLL RTError IndexProperty_SetFillFactor( IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetFillFactor", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("FillFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFillFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFillFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFillFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetFillFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFillFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FillFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property FillFactor must be Tools::VT_DOUBLE", + "IndexProperty_GetFillFactor"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FillFactor was empty", + "IndexProperty_GetFillFactor"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetSplitDistributionFactor( IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetSplitDistributionFactor", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("SplitDistributionFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetSplitDistributionFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetSplitDistributionFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetSplitDistributionFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetSplitDistributionFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetSplitDistributionFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("SplitDistributionFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property SplitDistributionFactor must be Tools::VT_DOUBLE", + "IndexProperty_GetSplitDistributionFactor"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property SplitDistributionFactor was empty", + "IndexProperty_GetSplitDistributionFactor"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetTPRHorizon(IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetTPRHorizon", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("Horizon", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetTPRHorizon"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetTPRHorizon"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetTPRHorizon"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetTPRHorizon(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetTPRHorizon", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Horizon"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property Horizon must be Tools::VT_DOUBLE", + "IndexProperty_GetTPRHorizon"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property Horizon was empty", + "IndexProperty_GetTPRHorizon"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetReinsertFactor( IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetReinsertFactor", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("ReinsertFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetReinsertFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetReinsertFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetReinsertFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetReinsertFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetReinsertFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("ReinsertFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property ReinsertFactor must be Tools::VT_DOUBLE", + "IndexProperty_GetReinsertFactor"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property ReinsertFactor was empty", + "IndexProperty_GetReinsertFactor"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetFileName( IndexPropertyH hProp, + const char* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetFileName", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = STRDUP(value); // not sure if we should copy here + prop->setProperty("FileName", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFileName"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFileName"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFileName"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL char* IndexProperty_GetFileName(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFileName", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FileName"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) { + Error_PushError(RT_Failure, + "Property FileName must be Tools::VT_PCHAR", + "IndexProperty_GetFileName"); + return NULL; + } + + return STRDUP(var.m_val.pcVal); + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FileName was empty", + "IndexProperty_GetFileName"); + return NULL; +} + + +SIDX_C_DLL RTError IndexProperty_SetFileNameExtensionDat( IndexPropertyH hProp, + const char* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetFileNameExtensionDat", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = STRDUP(value); // not sure if we should copy here + prop->setProperty("FileNameDat", var); + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFileNameExtensionDat"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFileNameExtensionDat"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFileNameExtensionDat"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL char* IndexProperty_GetFileNameExtensionDat(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFileNameExtensionDat", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FileNameDat"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) { + Error_PushError(RT_Failure, + "Property FileNameDat must be Tools::VT_PCHAR", + "IndexProperty_GetFileNameExtensionDat"); + return NULL; + } + + return STRDUP(var.m_val.pcVal); + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FileNameDat was empty", + "IndexProperty_GetFileNameExtensionDat"); + return NULL; +} + +SIDX_C_DLL RTError IndexProperty_SetFileNameExtensionIdx( IndexPropertyH hProp, + const char* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetFileNameExtensionIdx", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = STRDUP(value); // not sure if we should copy here + prop->setProperty("FileNameIdx", var); + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFileNameExtensionIdx"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFileNameExtensionIdx"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFileNameExtensionIdx"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL char* IndexProperty_GetFileNameExtensionIdx(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFileNameExtensionIdx", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FileNameIdx"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) { + Error_PushError(RT_Failure, + "Property FileNameIdx must be Tools::VT_PCHAR", + "IndexProperty_GetFileNameExtensionIdx"); + return NULL; + } + + return STRDUP(var.m_val.pcVal); + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FileNameIdx was empty", + "IndexProperty_GetFileNameExtensionIdx"); + return NULL; +} + +SIDX_C_DLL RTError IndexProperty_SetCustomStorageCallbacksSize(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetCustomStorageCallbacksSize", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("CustomStorageCallbacksSize", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetCustomStorageCallbacksSize"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetCustomStorageCallbacksSize"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetCustomStorageCallbacksSize"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetCustomStorageCallbacksSize(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetCustomStorageCallbacksSize", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("CustomStorageCallbacksSize"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property CustomStorageCallbacksSize must be Tools::VT_ULONG", + "IndexProperty_GetCustomStorageCallbacksSize"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property CustomStorageCallbacksSize was empty", + "IndexProperty_GetCustomStorageCallbacksSize"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetCustomStorageCallbacks( IndexPropertyH hProp, + const void* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetCustomStorageCallbacks", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + // check if the CustomStorageCallbacksSize is alright, so we can make a copy of the passed in structure + Tools::Variant varSize; + varSize = prop->getProperty("CustomStorageCallbacksSize"); + if ( varSize.m_val.ulVal != sizeof(SpatialIndex::StorageManager::CustomStorageManagerCallbacks) ) + { + std::ostringstream ss; + ss << "The supplied storage callbacks size is wrong, expected " + << sizeof(SpatialIndex::StorageManager::CustomStorageManagerCallbacks) + << ", got " << varSize.m_val.ulVal; + Error_PushError(RT_Failure, + ss.str().c_str(), + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PVOID; + var.m_val.pvVal = value ? + new SpatialIndex::StorageManager::CustomStorageManagerCallbacks( + *static_cast<const SpatialIndex::StorageManager::CustomStorageManagerCallbacks*>(value) + ) + : 0; + prop->setProperty("CustomStorageCallbacks", var); + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL void* IndexProperty_GetCustomStorageCallbacks(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetCustomStorageCallbacks", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("CustomStorageCallbacks"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PVOID) { + Error_PushError(RT_Failure, + "Property CustomStorageCallbacks must be Tools::VT_PVOID", + "IndexProperty_GetCustomStorageCallbacks"); + return NULL; + } + + return var.m_val.pvVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property CustomStorageCallbacks was empty", + "IndexProperty_GetCustomStorageCallbacks"); + return NULL; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexID(IndexPropertyH hProp, + int64_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexID", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = value; + prop->setProperty("IndexIdentifier", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexID"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexID"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexID"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL int64_t IndexProperty_GetIndexID(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexID", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexIdentifier"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONGLONG) { + Error_PushError(RT_Failure, + "Property IndexIdentifier must be Tools::VT_LONGLONG", + "IndexProperty_GetIndexID"); + return 0; + } + + return var.m_val.llVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property IndexIdentifier was empty", + "IndexProperty_GetIndexID"); + return 0; +} + +SIDX_C_DLL void* SIDX_NewBuffer(size_t length) +{ + return new char[length]; +} + +SIDX_C_DLL void SIDX_DeleteBuffer(void* buffer) +{ + delete []buffer; +} + + +SIDX_C_DLL char* SIDX_Version() +{ + + std::ostringstream ot; + +#ifdef SIDX_RELEASE_NAME + ot << SIDX_RELEASE_NAME; +#else + ot << "1.3.2"; +#endif + + std::string out(ot.str()); + return STRDUP(out.c_str()); + +} +IDX_C_END diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/BoundsQuery.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/BoundsQuery.cc new file mode 100644 index 000000000..a7cedb2c4 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/BoundsQuery.cc @@ -0,0 +1,45 @@ +/****************************************************************************** + * $Id: boundsquery.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the bounds query. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <capi/sidx_impl.h> + +BoundsQuery::BoundsQuery() +{ + m_bounds = new SpatialIndex::Region; +} + +void BoundsQuery::getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext) +{ + SpatialIndex::IShape* ps; + entry.getShape(&ps); + ps->getMBR(*m_bounds); + delete ps; + + hasNext = false; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/CountVisitor.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/CountVisitor.cc new file mode 100644 index 000000000..2fe7e940c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/CountVisitor.cc @@ -0,0 +1,52 @@ + +/****************************************************************************** +* $Id$ +* +* Project: libsidx - A C API wrapper around libspatialindex +* Purpose: C++ objects to implement the count visitor. +* Author: Leonard Norrgård, leonard.norrgard@refactor.fi +* +****************************************************************************** +* Copyright (c) 2010, Leonard Norrgård +* +* All rights reserved. +* +* This library is free software; you can redistribute it and/or modify it under +* the terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; either version 2.1 of the License, or (at your option) +* any later version. + +* This library is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +* details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this library; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#include "sidx_impl.h" + +CountVisitor::CountVisitor(): nResults(0) +{ +} + +CountVisitor::~CountVisitor() +{ + +} + +void CountVisitor::visitNode(const SpatialIndex::INode& n) +{ + +} + +void CountVisitor::visitData(const SpatialIndex::IData& d) +{ + nResults += 1; +} + +void CountVisitor::visitData(std::vector<const SpatialIndex::IData*>& v) +{ +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/CustomStorage.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/CustomStorage.cc new file mode 100644 index 000000000..e35c00e4d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/CustomStorage.cc @@ -0,0 +1,110 @@ +/****************************************************************************** + * $Id: CustomStorage.cc 1385 2009-06-17 13:45:16Z nitro $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ object declarations to implement the custom storage manager. + * Author: Matthias (nitro) + * + ****************************************************************************** + * Copyright (c) 2010, Matthias (nitro) + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "../spatialindex/SpatialIndexImpl.h" +#include "sidx_impl.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + + +IStorageManager* SpatialIndex::StorageManager::returnCustomStorageManager(Tools::PropertySet& ps) +{ + IStorageManager* sm = new CustomStorageManager(ps); + return sm; +} + +CustomStorageManager::CustomStorageManager(Tools::PropertySet& ps) +{ + Tools::Variant var; + var = ps.getProperty("CustomStorageCallbacks"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PVOID) + throw Tools::IllegalArgumentException("CustomStorageManager: Property CustomStorageCallbacks must be Tools::VT_PVOID"); + + if (!var.m_val.pvVal) + throw Tools::IllegalArgumentException("CustomStorageManager: Property CustomStorageCallbacks must not be 0."); + + // we already checked for validity in IndexProperty_SetCustomStorageCallbacks + CustomStorageManagerCallbacks* callbackArray = static_cast<CustomStorageManagerCallbacks*>(var.m_val.pvVal); + callbacks = *callbackArray; + } + + int errorCode( NoError ); + if ( callbacks.createCallback ) callbacks.createCallback( callbacks.context, &errorCode ); + processErrorCode( errorCode, NewPage ); +} + +CustomStorageManager::~CustomStorageManager() +{ + int errorCode( NoError ); + if ( callbacks.destroyCallback ) callbacks.destroyCallback( callbacks.context, &errorCode ); + processErrorCode( errorCode, NewPage ); +} + +void CustomStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + int errorCode( NoError ); + if ( callbacks.loadByteArrayCallback ) callbacks.loadByteArrayCallback( callbacks.context, page, &len, data, &errorCode ); + processErrorCode( errorCode, page ); +} + +void CustomStorageManager::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + int errorCode( NoError ); + if ( callbacks.storeByteArrayCallback ) callbacks.storeByteArrayCallback( callbacks.context, &page, len, data, &errorCode ); + processErrorCode( errorCode, page ); +} + +void CustomStorageManager::deleteByteArray(const id_type page) +{ + int errorCode( NoError ); + if ( callbacks.deleteByteArrayCallback ) callbacks.deleteByteArrayCallback( callbacks.context, page, &errorCode ); + processErrorCode( errorCode, page ); +} + +inline void CustomStorageManager::processErrorCode(int errorCode, const id_type page) +{ + switch (errorCode) + { + case NoError: + break; + + case InvalidPageError: + throw InvalidPageException( page ); + break; + + case IllegalStateError: + throw Tools::IllegalStateException( "CustomStorageManager: Error in user implementation." ); + break; + + default: + throw Tools::IllegalStateException( "CustomStorageManager: Unknown error." ); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/DataStream.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/DataStream.cc new file mode 100644 index 000000000..d30d70ec8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/DataStream.cc @@ -0,0 +1,103 @@ +/****************************************************************************** + * $Id: datastream.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the datastream. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + + +DataStream::DataStream(int (*readNext)(SpatialIndex::id_type * id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t** pData, uint32_t *nDataLength)) :m_pNext(0),m_bDoneReading(false) +{ + iterfunct = readNext; + + // Read the first one. + readData(); +} + +DataStream::~DataStream() +{ + if (m_pNext != 0) delete m_pNext; +} + +bool DataStream::readData() +{ + SpatialIndex::id_type id; + double *pMin=0; + double *pMax=0; + uint32_t nDimension=0; + const uint8_t *p_data=0; + uint32_t nDataLength=0; + + if (m_bDoneReading == true) { + return false; + } + + int ret = iterfunct(&id, &pMin, &pMax, &nDimension, &p_data, &nDataLength); + + // The callback should return anything other than 0 + // when it is done. + if (ret != 0) + { + m_bDoneReading = true; + return false; + } + + SpatialIndex::Region r = SpatialIndex::Region(pMin, pMax, nDimension); + m_pNext = new SpatialIndex::RTree::Data(nDataLength, (byte*)p_data, r, id); + + return true; +} + + +SpatialIndex::IData* DataStream::getNext() +{ + if (m_pNext == 0) return 0; + + SpatialIndex::RTree::Data* ret = m_pNext; + m_pNext = 0; + readData(); + return ret; +} + +bool DataStream::hasNext() throw (Tools::NotSupportedException) +{ + return (m_pNext != 0); +} + +uint32_t DataStream::size() throw (Tools::NotSupportedException) +{ + throw Tools::NotSupportedException("Operation not supported."); +} + +void DataStream::rewind() throw (Tools::NotSupportedException) +{ + throw Tools::NotSupportedException("Operation not supported."); + + if (m_pNext != 0) + { + delete m_pNext; + m_pNext = 0; + } +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/Error.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/Error.cc new file mode 100644 index 000000000..19239710b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/Error.cc @@ -0,0 +1,54 @@ +/****************************************************************************** + * $Id: error.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the error object. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +Error::Error(int code, std::string const& message, std::string const& method) : + m_code(code), + m_message(message), + m_method(method) +{ +} + +Error::Error(Error const& other) : + m_code(other.m_code), + m_message(other.m_message), + m_method(other.m_method) +{ +} + +Error& Error::operator=(Error const& rhs) +{ + if (&rhs != this) + { + m_code = rhs.m_code; + m_message = rhs.m_message; + m_method = rhs.m_method; + + } + return *this; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/IdVisitor.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/IdVisitor.cc new file mode 100644 index 000000000..7e0e0b615 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/IdVisitor.cc @@ -0,0 +1,53 @@ +/****************************************************************************** + * $Id: idvisitor.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the id visitor. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +IdVisitor::IdVisitor(): nResults(0) +{ +} + +IdVisitor::~IdVisitor() +{ + +} + +void IdVisitor::visitNode(const SpatialIndex::INode& n) +{ + +} + +void IdVisitor::visitData(const SpatialIndex::IData& d) +{ + nResults += 1; + + m_vector.push_back(d.getIdentifier()); +} + +void IdVisitor::visitData(std::vector<const SpatialIndex::IData*>& v) +{ +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/Index.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/Index.cc new file mode 100644 index 000000000..98736043c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/Index.cc @@ -0,0 +1,381 @@ +/****************************************************************************** + * $Id: index.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the index. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +SpatialIndex::ISpatialIndex* Index::CreateIndex() +{ + using namespace SpatialIndex; + + ISpatialIndex* index = 0; + + Tools::Variant var; + + if (GetIndexType() == RT_RTree) { + + try { + index = RTree::returnRTree( *m_buffer, m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + } + + else if (GetIndexType() == RT_MVRTree) { + + try { + index = MVRTree::returnMVRTree( *m_buffer, m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + } + + else if (GetIndexType() == RT_TPRTree) { + + try { + index = TPRTree::returnTPRTree( *m_buffer,m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + } + + return index; +} + + +Index::Index(const Tools::PropertySet& poProperties) +{ + Setup(); + + m_properties = poProperties; + + Initialize(); +} + + +Index::~Index() +{ + if (m_rtree != 0) + delete m_rtree; + if (m_buffer != 0) + delete m_buffer; + if (m_storage != 0) + delete m_storage; + +} + +Index::Index( const Tools::PropertySet& poProperties, + int (*readNext)(SpatialIndex::id_type *id, + double **pMin, + double **pMax, + uint32_t *nDimension, + const uint8_t **pData, + uint32_t *nDataLength)) +{ + using namespace SpatialIndex; + + Setup(); + + m_properties = poProperties; + + m_storage = CreateStorage(); + m_buffer = CreateIndexBuffer(*m_storage); + + DataStream ds(readNext); + + double dFillFactor = 0.7; + uint32_t nIdxCapacity = 100; + uint32_t nIdxLeafCap = 100; + uint32_t nIdxDimension = 2; + SpatialIndex::RTree::RTreeVariant eVariant = SpatialIndex::RTree::RV_RSTAR; + SpatialIndex::id_type m_IdxIdentifier; + + // Fetch a bunch of properties. We can't bulk load an rtree using merely + // properties, we have to use the helper method(s). + + Tools::Variant var; + var = m_properties.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) + throw std::runtime_error("Index::Index (streaming):" + " Property FillFactor must be Tools::VT_DOUBLE"); + + dFillFactor = var.m_val.dblVal; + } + + var = m_properties.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::Index (streaming): " + "Property IndexCapacity must be Tools::VT_ULONG"); + + nIdxCapacity = var.m_val.ulVal; + } + + var = m_properties.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::Index (streaming): " + "Property LeafCapacity must be Tools::VT_ULONG"); + + nIdxLeafCap = var.m_val.ulVal; + } + + var = m_properties.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::Index (streaming): " + "Property Dimension must be Tools::VT_ULONG"); + + nIdxDimension = var.m_val.ulVal; + } + + var = m_properties.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG) + throw std::runtime_error("Index::Index (streaming): " + "Property TreeVariant must be Tools::VT_LONG"); + + eVariant = static_cast<SpatialIndex::RTree::RTreeVariant>(var.m_val.lVal); + } + + var = m_properties.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONGLONG) + throw std::runtime_error("Index::Index (streaming): " + "Property IndexIdentifier must be Tools::VT_LONGLONG"); + + m_IdxIdentifier = var.m_val.llVal; + } + + m_rtree = RTree::createAndBulkLoadNewRTree( SpatialIndex::RTree::BLM_STR, + ds, + *m_buffer, + dFillFactor, + nIdxCapacity, + nIdxLeafCap, + nIdxDimension, + eVariant, + m_IdxIdentifier); +} + + +SpatialIndex::StorageManager::IBuffer* Index::CreateIndexBuffer(SpatialIndex::IStorageManager& storage) +{ + using namespace SpatialIndex::StorageManager; + IBuffer* buffer = 0; + try { + if ( m_storage == 0 ) + throw std::runtime_error("Storage was invalid to create index buffer"); + buffer = returnRandomEvictionsBuffer(storage, m_properties); + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + return buffer; +} + + +SpatialIndex::IStorageManager* Index::CreateStorage() +{ + using namespace SpatialIndex::StorageManager; + + SpatialIndex::IStorageManager* storage = 0; + std::string filename(""); + + Tools::Variant var; + var = m_properties.getProperty("FileName"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) + throw std::runtime_error("Index::CreateStorage: " + "Property FileName must be Tools::VT_PCHAR"); + + filename = std::string(var.m_val.pcVal); + } + + if (GetIndexStorage() == RT_Disk) { + if (filename.empty()) { + std::ostringstream os; + os << "Spatial Index Error: filename was empty." + " Set IndexStorageType to RT_Memory"; + throw std::runtime_error(os.str()); + } + try { + storage = returnDiskStorageManager(m_properties); + return storage; + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + + } else if (GetIndexStorage() == RT_Memory) { + + try { + storage = returnMemoryStorageManager(m_properties); + return storage; + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + + } else if (GetIndexStorage() == RT_Custom) { + + try { + storage = returnCustomStorageManager(m_properties); + return storage; + } catch (Tools::Exception& e) { + std::ostringstream os; + os << "Spatial Index Error: " << e.what(); + throw std::runtime_error(os.str()); + } + + } + return storage; +} + + + + +void Index::Initialize() +{ + m_storage = CreateStorage(); + m_buffer = CreateIndexBuffer(*m_storage); + m_rtree = CreateIndex(); +} + +void Index::Setup() + +{ + m_buffer = 0; + m_storage = 0; + m_rtree = 0; +} + +RTIndexType Index::GetIndexType() +{ + Tools::Variant var; + var = m_properties.getProperty("IndexType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::GetIndexType: " + "Property IndexType must be Tools::VT_ULONG"); + + return static_cast<RTIndexType>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + return RT_InvalidIndexType; + +} +void Index::SetIndexType(RTIndexType v) +{ + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = v; + m_properties.setProperty("IndexType", var); +} + +RTStorageType Index::GetIndexStorage() +{ + + Tools::Variant var; + var = m_properties.getProperty("IndexStorageType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::GetIndexStorage: " + "Property IndexStorageType must be Tools::VT_ULONG"); + + return static_cast<RTStorageType>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + return RT_InvalidStorageType; +} + +void Index::SetIndexStorage(RTStorageType v) +{ + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = v; + m_properties.setProperty("IndexStorageType", var); +} + +RTIndexVariant Index::GetIndexVariant() +{ + + Tools::Variant var; + var = m_properties.getProperty("TreeVariant"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw std::runtime_error("Index::GetIndexVariant: " + "Property TreeVariant must be Tools::VT_ULONG"); + + return static_cast<RTIndexVariant>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + return RT_InvalidIndexVariant; +} + +void Index::SetIndexVariant(RTStorageType v) +{ + using namespace SpatialIndex; + Tools::Variant var; + + if (GetIndexType() == RT_RTree) { + var.m_val.ulVal = static_cast<RTree::RTreeVariant>(v); + m_properties.setProperty("TreeVariant", var); + } else if (GetIndexType() == RT_MVRTree) { + var.m_val.ulVal = static_cast<MVRTree::MVRTreeVariant>(v); + m_properties.setProperty("TreeVariant", var); + } else if (GetIndexType() == RT_TPRTree) { + var.m_val.ulVal = static_cast<TPRTree::TPRTreeVariant>(v); + m_properties.setProperty("TreeVariant", var); + } +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/LeafQuery.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/LeafQuery.cc new file mode 100644 index 000000000..0d0998278 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/LeafQuery.cc @@ -0,0 +1,126 @@ +/****************************************************************************** + * $Id: boundsquery.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement a query of the index's leaves. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <capi/sidx_impl.h> + +LeafQuery::LeafQuery() +{ + +} + +LeafQueryResult get_results(const SpatialIndex::INode* n) +{ + LeafQueryResult result (n->getIdentifier()); + + SpatialIndex::IShape* ps; + n->getShape(&ps); + SpatialIndex::Region* pr = dynamic_cast<SpatialIndex::Region*>(ps); + std::vector<SpatialIndex::id_type> ids; + for (size_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + ids.push_back(n->getChildIdentifier(cChild)); + } + + result.SetIDs(ids); + result.SetBounds(pr); + delete ps; + + return result; +} +void LeafQuery::getNextEntry( const SpatialIndex::IEntry& entry, + SpatialIndex::id_type& nextEntry, + bool& hasNext) +{ + + const SpatialIndex::INode* n = dynamic_cast<const SpatialIndex::INode*>(&entry); + + // traverse only index nodes at levels 2 and higher. + if (n != 0 && n->getLevel() > 0) + { + for (uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++) + { + m_ids.push(n->getChildIdentifier(cChild)); + } + } + + if (n->isLeaf()) { + m_results.push_back(get_results(n)); + } + + if (! m_ids.empty()) + { + nextEntry = m_ids.front(); m_ids.pop(); + hasNext = true; + } + else + { + hasNext = false; + } +} + + +std::vector<SpatialIndex::id_type> const& LeafQueryResult::GetIDs() const +{ + return ids; +} + +void LeafQueryResult::SetIDs(std::vector<SpatialIndex::id_type>& v) +{ + ids.resize(v.size()); + std::copy(v.begin(), v.end(), ids.begin()); +} +const SpatialIndex::Region* LeafQueryResult::GetBounds() const +{ + return bounds; +} + +void LeafQueryResult::SetBounds(const SpatialIndex::Region* b) +{ + bounds = new SpatialIndex::Region(*b); +} + +LeafQueryResult::LeafQueryResult(LeafQueryResult const& other) +{ + ids.resize(other.ids.size()); + std::copy(other.ids.begin(), other.ids.end(), ids.begin()); + m_id = other.m_id; + + bounds = other.bounds->clone(); +} + +LeafQueryResult& LeafQueryResult::operator=(LeafQueryResult const& rhs) +{ + if (&rhs != this) + { + ids.resize(rhs.ids.size()); + std::copy(rhs.ids.begin(), rhs.ids.end(), ids.begin()); + m_id = rhs.m_id; + bounds = rhs.bounds->clone(); + } + return *this; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/capi/Makefile.am new file mode 100644 index 000000000..2c35d4002 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/Makefile.am @@ -0,0 +1,14 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libsidxc.la +INCLUDES = -I../../include -I../../include/capi +libsidxc_la_SOURCES = BoundsQuery.cc \ + CountVisitor.cc \ + CustomStorage.cc \ + DataStream.cc \ + Error.cc \ + IdVisitor.cc \ + Index.cc \ + LeafQuery.cc \ + ObjVisitor.cc \ + sidx_api.cc \ + Utility.cc diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/ObjVisitor.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/ObjVisitor.cc new file mode 100644 index 000000000..436f7b9a9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/ObjVisitor.cc @@ -0,0 +1,60 @@ +/****************************************************************************** + * $Id: objvisitor.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement the wrapper. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +ObjVisitor::ObjVisitor(): nResults(0) +{ +} + +ObjVisitor::~ObjVisitor() +{ + std::vector<SpatialIndex::IData*>::iterator it; + for (it = m_vector.begin(); it != m_vector.end(); it++) { + delete *it; + } + +} + +void ObjVisitor::visitNode(const SpatialIndex::INode& n) +{ +} + +void ObjVisitor::visitData(const SpatialIndex::IData& d) +{ + + SpatialIndex::IData* item = dynamic_cast<SpatialIndex::IData*>(const_cast<SpatialIndex::IData&>(d).clone()) ; + + nResults += 1; + + m_vector.push_back(item); +} + +void ObjVisitor::visitData(std::vector<const SpatialIndex::IData*>& v) +{ +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/Utility.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/Utility.cc new file mode 100644 index 000000000..e441853c3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/Utility.cc @@ -0,0 +1,150 @@ +/****************************************************************************** + * $Id: util.cc 1361 2009-08-02 17:53:31Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C++ objects to implement utilities. + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sidx_impl.h" + +Tools::PropertySet* GetDefaults() +{ + Tools::PropertySet* ps = new Tools::PropertySet; + + Tools::Variant var; + + // Rtree defaults + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 0.7; + ps->setProperty("FillFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = SpatialIndex::RTree::RV_RSTAR; + ps->setProperty("TreeVariant", var); + + // var.m_varType = Tools::VT_LONGLONG; + // var.m_val.llVal = 0; + // ps->setProperty("IndexIdentifier", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 32; + ps->setProperty("NearMinimumOverlapFactor", var); + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 0.4; + ps->setProperty("SplitDistributionFactor", var); + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 0.3; + ps->setProperty("ReinsertFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 2; + ps->setProperty("Dimension", var); + + var.m_varType = Tools::VT_BOOL; + var.m_val.bVal = true; + ps->setProperty("EnsureTightMBRs", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("IndexPoolCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 100; + ps->setProperty("LeafPoolCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 1000; + ps->setProperty("RegionPoolCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 500; + ps->setProperty("PointPoolCapacity", var); + + // horizon for TPRTree + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = 20.0; + ps->setProperty("Horizon", var); + + // Buffering defaults + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 10; + ps->setProperty("Capacity", var); + + var.m_varType = Tools::VT_BOOL; + var.m_val.bVal = false; + ps->setProperty("WriteThrough", var); + + // Disk Storage Manager defaults + var.m_varType = Tools::VT_BOOL; + var.m_val.bVal = true; + ps->setProperty("Overwrite", var); + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>(""); + ps->setProperty("FileName", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = 4096; + ps->setProperty("PageSize", var); + + // Our custom properties related to whether + // or not we are using a disk or memory storage manager + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = RT_Disk; + ps->setProperty("IndexStorageType", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = RT_RTree; + ps->setProperty("IndexType", var); + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>("dat"); + ps->setProperty("FileNameDat", var); + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>("idx"); + ps->setProperty("FileNameIdx", var); + + // Custom storage manager properties + var.m_varType = Tools::VT_ULONG; + var.m_val.pcVal = 0; + ps->setProperty("CustomStorageCallbacksSize", var); + + var.m_varType = Tools::VT_PVOID; + var.m_val.pcVal = 0; + ps->setProperty("CustomStorageCallbacks", var); + + return ps; +}
\ No newline at end of file diff --git a/sci-libs/libspatialindex/svn/trunk/src/capi/sidx_api.cc b/sci-libs/libspatialindex/svn/trunk/src/capi/sidx_api.cc new file mode 100644 index 000000000..e2b24c98f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/capi/sidx_api.cc @@ -0,0 +1,2518 @@ +/****************************************************************************** + * $Id: sidx_api.cc 1385 2009-08-13 15:45:16Z hobu $ + * + * Project: libsidx - A C API wrapper around libspatialindex + * Purpose: C API wrapper implementation + * Author: Howard Butler, hobu.inc@gmail.com + * + ****************************************************************************** + * Copyright (c) 2009, Howard Butler + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include <cmath> +#include <limits> +#include "sidx_impl.h" + +static std::stack<Error> errors; + +#define VALIDATE_POINTER0(ptr, func) \ + do { if( NULL == ptr ) { \ + RTError const ret = RT_Failure; \ + std::ostringstream msg; \ + msg << "Pointer \'" << #ptr << "\' is NULL in \'" << (func) <<"\'."; \ + std::string message(msg.str()); \ + Error_PushError( ret, message.c_str(), (func)); \ + return; \ + }} while(0) + +#define VALIDATE_POINTER1(ptr, func, rc) \ + do { if( NULL == ptr ) { \ + RTError const ret = RT_Failure; \ + std::ostringstream msg; \ + msg << "Pointer \'" << #ptr << "\' is NULL in \'" << (func) <<"\'."; \ + std::string message(msg.str()); \ + Error_PushError( ret, message.c_str(), (func)); \ + return (rc); \ + }} while(0) + +IDX_C_START + +SIDX_C_DLL void Error_Reset(void) { + if (errors.empty()) return; + for (std::size_t i=0;i<errors.size();i++) errors.pop(); +} + +SIDX_C_DLL void Error_Pop(void) { + if (errors.empty()) return; + errors.pop(); +} + +SIDX_C_DLL int Error_GetLastErrorNum(void){ + if (errors.empty()) + return 0; + else { + Error err = errors.top(); + return err.GetCode(); + } +} + +SIDX_C_DLL char* Error_GetLastErrorMsg(void){ + if (errors.empty()) + return NULL; + else { + Error err = errors.top(); + return STRDUP(err.GetMessage()); + } +} + +SIDX_C_DLL char* Error_GetLastErrorMethod(void){ + if (errors.empty()) + return NULL; + else { + Error err = errors.top(); + return STRDUP(err.GetMethod()); + } +} + +SIDX_C_DLL void Error_PushError(int code, const char *message, const char *method) { + Error err = Error(code, std::string(message), std::string(method)); + errors.push(err); +} + +SIDX_C_DLL int Error_GetErrorCount(void) { + return static_cast<int>(errors.size()); +} + +SIDX_C_DLL IndexH Index_Create(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "Index_Create", NULL); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try { + return (IndexH) new Index(*prop); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Create"); + return NULL; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Create"); + return NULL; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Create"); + return NULL; + } + return NULL; +} + +SIDX_C_DLL IndexH Index_CreateWithStream( IndexPropertyH hProp, + int (*readNext)(SpatialIndex::id_type *id, double **pMin, double **pMax, uint32_t *nDimension, const uint8_t **pData, uint32_t *nDataLength) + ) +{ + VALIDATE_POINTER1(hProp, "Index_CreateWithStream", NULL); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + + try { + return (IndexH) new Index(*prop, readNext); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_CreateWithStream"); + return NULL; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_CreateWithStream"); + return NULL; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_CreateWithStream"); + return NULL; + } + return NULL; +} + +SIDX_C_DLL void Index_Destroy(IndexH index) +{ + VALIDATE_POINTER0(index, "Index_Destroy"); + Index* idx = (Index*) index; + if (idx) delete idx; +} + +SIDX_C_DLL RTError Index_DeleteData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension) +{ + VALIDATE_POINTER1(index, "Index_DeleteData", RT_Failure); + + Index* idx = static_cast<Index*>(index); + + try { + idx->index().deleteData(SpatialIndex::Region(pdMin, pdMax, nDimension), id); + return RT_None; + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_DeleteData"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_DeleteData"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_DeleteData"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_InsertData( IndexH index, + uint64_t id, + double* pdMin, + double* pdMax, + uint32_t nDimension, + const uint8_t* pData, + uint32_t nDataLength) +{ + VALIDATE_POINTER1(index, "Index_InsertData", RT_Failure); + + Index* idx = static_cast<Index*>(index); + + // Test the data and check for the case when minx == maxx, miny == maxy + // and minz == maxz. In that case, we will insert a SpatialIndex::Point + // instead of a SpatialIndex::Region + + bool isPoint = false; + SpatialIndex::IShape* shape = 0; + double const epsilon = std::numeric_limits<double>::epsilon(); + + double length(0); + for (uint32_t i = 0; i < nDimension; ++i) { + double delta = pdMin[i] - pdMax[i]; + length += std::fabs(delta); + } + + if (length <= epsilon) { + isPoint = true; + } + + if (isPoint == true) { + shape = new SpatialIndex::Point(pdMin, nDimension); + } else { + shape = new SpatialIndex::Region(pdMin, pdMax, nDimension); + } + try { + idx->index().insertData(nDataLength, + pData, + *shape, + id); + + delete shape; + return RT_None; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_InsertData"); + delete shape; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_InsertData"); + delete shape; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_InsertData"); + delete shape; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_Intersects_obj( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_Intersects_obj", RT_Failure); + Index* idx = static_cast<Index*>(index); + + ObjVisitor* visitor = new ObjVisitor; + try { + SpatialIndex::Region* r = new SpatialIndex::Region(pdMin, pdMax, nDimension); + idx->index().intersectsWithQuery( *r, + *visitor); + + *items = (SpatialIndex::IData**) malloc (visitor->GetResultCount() * sizeof(SpatialIndex::IData*)); + + std::vector<SpatialIndex::IData*>& results = visitor->GetResults(); + + // copy the Items into the newly allocated item array + // we need to make sure to copy the actual Item instead + // of just the pointers, as the visitor will nuke them + // upon ~ + for (uint32_t i=0; i < visitor->GetResultCount(); ++i) + { + SpatialIndex::IData* result =results[i]; + (*items)[i] = dynamic_cast<SpatialIndex::IData*>(result->clone()); + + } + *nResults = visitor->GetResultCount(); + + delete r; + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Intersects_obj"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Intersects_obj"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Intersects_obj"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_Intersects_id( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** ids, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_Intersects_id", RT_Failure); + Index* idx = static_cast<Index*>(index); + + IdVisitor* visitor = new IdVisitor; + try { + SpatialIndex::Region* r = new SpatialIndex::Region(pdMin, pdMax, nDimension); + idx->index().intersectsWithQuery( *r, + *visitor); + + *nResults = visitor->GetResultCount(); + + *ids = (uint64_t*) malloc (*nResults * sizeof(uint64_t)); + + std::vector<uint64_t>& results = visitor->GetResults(); + + for (uint32_t i=0; i < *nResults; ++i) + { + (*ids)[i] = results[i]; + + } + + delete r; + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Intersects_id"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Intersects_id"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Intersects_id"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_Intersects_count( IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_Intersects_count", RT_Failure); + Index* idx = static_cast<Index*>(index); + + CountVisitor* visitor = new CountVisitor; + try { + SpatialIndex::Region* r = new SpatialIndex::Region(pdMin, pdMax, nDimension); + idx->index().intersectsWithQuery( *r, + *visitor); + + *nResults = visitor->GetResultCount(); + + delete r; + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_Intersects_count"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_Intersects_count"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_Intersects_count"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_NearestNeighbors_id(IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + uint64_t** ids, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_NearestNeighbors_id", RT_Failure); + Index* idx = static_cast<Index*>(index); + + IdVisitor* visitor = new IdVisitor; + + try { + idx->index().nearestNeighborQuery( *nResults, + SpatialIndex::Region(pdMin, pdMax, nDimension), + *visitor); + + *ids = (uint64_t*) malloc (visitor->GetResultCount() * sizeof(uint64_t)); + + std::vector<uint64_t>& results = visitor->GetResults(); + + *nResults = results.size(); + + for (uint32_t i=0; i < *nResults; ++i) + { + (*ids)[i] = results[i]; + + } + + + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_NearestNeighbors_id"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_NearestNeighbors_id"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_NearestNeighbors_id"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_NearestNeighbors_obj(IndexH index, + double* pdMin, + double* pdMax, + uint32_t nDimension, + IndexItemH** items, + uint64_t* nResults) +{ + VALIDATE_POINTER1(index, "Index_NearestNeighbors_obj", RT_Failure); + Index* idx = static_cast<Index*>(index); + + ObjVisitor* visitor = new ObjVisitor; + try { + idx->index().nearestNeighborQuery( *nResults, + SpatialIndex::Region(pdMin, pdMax, nDimension), + *visitor); + + + *items = (SpatialIndex::IData**) malloc (visitor->GetResultCount() * sizeof(Item*)); + + std::vector<SpatialIndex::IData*> results = visitor->GetResults(); + *nResults = results.size(); + + // copy the Items into the newly allocated item array + // we need to make sure to copy the actual Item instead + // of just the pointers, as the visitor will nuke them + // upon ~ + for (uint32_t i=0; i < visitor->GetResultCount(); ++i) + { + SpatialIndex::IData* result = results[i]; + (*items)[i] = dynamic_cast<SpatialIndex::IData*>(result->clone()); + + } + + delete visitor; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_NearestNeighbors_obj"); + delete visitor; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_NearestNeighbors_obj"); + delete visitor; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_NearestNeighbors_obj"); + delete visitor; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTError Index_GetBounds( IndexH index, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension) +{ + VALIDATE_POINTER1(index, "Index_GetBounds", RT_Failure); + Index* idx = static_cast<Index*>(index); + + BoundsQuery* query = new BoundsQuery; + + try { + idx->index().queryStrategy( *query); + + const SpatialIndex::Region* bounds = query->GetBounds(); + if (bounds == 0) { + *nDimension = 0; + delete query; + return RT_None; + } + + *nDimension =bounds->getDimension(); + + *ppdMin = (double*) malloc (*nDimension * sizeof(double)); + *ppdMax = (double*) malloc (*nDimension * sizeof(double)); + + for (uint32_t i=0; i< *nDimension; ++i) { + (*ppdMin)[i] = bounds->getLow(i); + (*ppdMax)[i] = bounds->getHigh(i); + } + + delete query; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_GetBounds"); + delete query; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_GetBounds"); + delete query; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_GetBounds"); + delete query; + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t Index_IsValid(IndexH index) +{ + VALIDATE_POINTER1(index, "Index_IsValid", 0); + Index* idx = static_cast<Index*>(index); + return static_cast<uint32_t>(idx->index().isIndexValid()); +} + +SIDX_C_DLL IndexPropertyH Index_GetProperties(IndexH index) +{ + VALIDATE_POINTER1(index, "Index_GetProperties", 0); + Index* idx = static_cast<Index*>(index); + Tools::PropertySet* ps = new Tools::PropertySet; + + idx->index().getIndexProperties(*ps); + return (IndexPropertyH)ps; +} + +SIDX_C_DLL IndexPropertyH Index_ClearBuffer(IndexH index) +{ + VALIDATE_POINTER1(index, "Index_ClearBuffer", 0); + Index* idx = static_cast<Index*>(index); + idx->buffer().clear(); +} + +SIDX_C_DLL void Index_DestroyObjResults(IndexItemH* results, uint32_t nResults) +{ + VALIDATE_POINTER0(results, "Index_DestroyObjResults"); + SpatialIndex::IData* it; + for (uint32_t i=0; i< nResults; ++i) { + if (results[i] != NULL) { + it = static_cast<SpatialIndex::IData*>(results[i]); + if (it != 0) + delete it; + } + } + + std::free(results); +} + + +SIDX_C_DLL void Index_Free(void* results) +{ + VALIDATE_POINTER0(results, "Index_Free"); + if (results != 0) + std::free(results); +} + +SIDX_C_DLL RTError Index_GetLeaves( IndexH index, + uint32_t* nNumLeafNodes, + uint32_t** nLeafSizes, + int64_t** nLeafIDs, + int64_t*** nLeafChildIDs, + double*** pppdMin, + double*** pppdMax, + uint32_t* nDimension) +{ + VALIDATE_POINTER1(index, "Index_GetLeaves", RT_Failure); + Index* idx = static_cast<Index*>(index); + + std::vector<LeafQueryResult>::const_iterator i; + LeafQuery* query = new LeafQuery; + + // Fetch the dimensionality of the index + Tools::PropertySet ps; + idx->index().getIndexProperties(ps); + + Tools::Variant var; + var = ps.getProperty("Dimension"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property Dimension must be Tools::VT_ULONG", + "Index_GetLeaves"); + return RT_Failure; + } + } + + *nDimension = var.m_val.ulVal; + + try { + idx->index().queryStrategy( *query); + + const std::vector<LeafQueryResult>& results = query->GetResults(); + + *nNumLeafNodes = results.size(); + + *nLeafSizes = (uint32_t*) malloc (*nNumLeafNodes * sizeof(uint32_t)); + *nLeafIDs = (int64_t*) malloc (*nNumLeafNodes * sizeof(int64_t)); + + *nLeafChildIDs = (int64_t**) malloc(*nNumLeafNodes * sizeof(int64_t*)); + *pppdMin = (double**) malloc (*nNumLeafNodes * sizeof(double*)); + *pppdMax = (double**) malloc (*nNumLeafNodes * sizeof(double*)); + + uint32_t k=0; + for (i = results.begin(); i != results.end(); ++i) + { + std::vector<SpatialIndex::id_type> const& ids = (*i).GetIDs(); + const SpatialIndex::Region* b = (*i).GetBounds(); + + (*nLeafIDs)[k] = (*i).getIdentifier(); + (*nLeafSizes)[k] = ids.size(); + + (*nLeafChildIDs)[k] = (int64_t*) malloc( (*nLeafSizes)[k] * sizeof(int64_t)); + (*pppdMin)[k] = (double*) malloc ( (*nLeafSizes)[k] * sizeof(double)); + (*pppdMax)[k] = (double*) malloc ( (*nLeafSizes)[k] * sizeof(double)); + for (uint32_t i=0; i< *nDimension; ++i) { + (*pppdMin)[k][i] = b->getLow(i); + (*pppdMax)[k][i] = b->getHigh(i); + } + for (uint32_t cChild = 0; cChild < ids.size(); cChild++) + { + (*nLeafChildIDs)[k][cChild] = ids[cChild]; + } + ++k; + } + + + delete query; + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "Index_GetLeaves"); + delete query; + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "Index_GetLeaves"); + delete query; + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "Index_GetLeaves"); + delete query; + return RT_Failure; + } + return RT_None; +} + + +SIDX_C_DLL void IndexItem_Destroy(IndexItemH item) +{ + VALIDATE_POINTER0(item, "IndexItem_Destroy"); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + if (it != 0) delete it; +} + +SIDX_C_DLL RTError IndexItem_GetData( IndexItemH item, + uint8_t** data, + uint64_t* length) +{ + VALIDATE_POINTER1(item, "IndexItem_GetData", RT_Failure); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + uint8_t* p_data; + uint32_t* l= new uint32_t; + + it->getData(*l,&p_data); + *length = (uint64_t)*l; + *data = (uint8_t*) malloc (*length * sizeof(uint8_t)); + + memcpy(*data, p_data, *length); + delete[] p_data; + delete l; + return RT_None; + +} + +SIDX_C_DLL uint64_t IndexItem_GetID(IndexItemH item) +{ + VALIDATE_POINTER1(item, "IndexItem_GetID",0); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + uint64_t value = it->getIdentifier(); + return value; +} + +SIDX_C_DLL RTError IndexItem_GetBounds( IndexItemH item, + double** ppdMin, + double** ppdMax, + uint32_t* nDimension) +{ + VALIDATE_POINTER1(item, "IndexItem_GetBounds", RT_Failure); + SpatialIndex::IData* it = static_cast<SpatialIndex::IData*>(item); + + SpatialIndex::IShape* s; + it->getShape(&s); + + SpatialIndex::Region *bounds = new SpatialIndex::Region(); + s->getMBR(*bounds); + + if (bounds == 0) { + *nDimension = 0; + delete bounds; + delete s; + return RT_None; + } + *nDimension = bounds->getDimension(); + + *ppdMin = (double*) malloc (*nDimension * sizeof(double)); + *ppdMax = (double*) malloc (*nDimension * sizeof(double)); + + if (ppdMin == NULL || ppdMax == NULL) { + Error_PushError(RT_Failure, + "Unable to allocation bounds array(s)", + "IndexItem_GetBounds"); + return RT_Failure; + } + + for (uint32_t i=0; i< *nDimension; ++i) { + (*ppdMin)[i] = bounds->getLow(i); + (*ppdMax)[i] = bounds->getHigh(i); + } + delete bounds; + delete s; + return RT_None; +} +SIDX_C_DLL IndexPropertyH IndexProperty_Create() +{ + Tools::PropertySet* ps = GetDefaults(); + Tools::Variant var; + return (IndexPropertyH)ps; +} + +SIDX_C_DLL void IndexProperty_Destroy(IndexPropertyH hProp) +{ + VALIDATE_POINTER0(hProp, "IndexProperty_Destroy"); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + if (prop != 0) delete prop; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexType(IndexPropertyH hProp, + RTIndexType value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexType", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (!(value == RT_RTree || value == RT_MVRTree || value == RT_TPRTree)) { + throw std::runtime_error("Inputted value is not a valid index type"); + } + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexType", var); + + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexType"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexType"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexType"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTIndexType IndexProperty_GetIndexType(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexType", RT_InvalidIndexType); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexType must be Tools::VT_ULONG", + "IndexProperty_GetIndexType"); + return RT_InvalidIndexType; + } + return (RTIndexType) var.m_val.ulVal; + } + + Error_PushError(RT_Failure, + "Property IndexType was empty", + "IndexProperty_GetIndexType"); + return RT_InvalidIndexType; + +} + +SIDX_C_DLL RTError IndexProperty_SetDimension(IndexPropertyH hProp, uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetDimension", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("Dimension", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetDimension"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetDimension"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetDimension"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetDimension(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetDimension", RT_InvalidIndexType); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Dimension"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexType must be Tools::VT_ULONG", + "IndexProperty_GetDimension"); + return 0; + } + + return var.m_val.ulVal; + } + + // A zero dimension index is invalid. + Error_PushError(RT_Failure, + "Property Dimension was empty", + "IndexProperty_GetDimension"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexVariant( IndexPropertyH hProp, + RTIndexVariant value) +{ + using namespace SpatialIndex; + + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexVariant", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + + try + { + + if (!(value == RT_Linear || value == RT_Quadratic || value == RT_Star)) { + throw std::runtime_error("Inputted value is not a valid index variant"); + } + + var.m_varType = Tools::VT_LONG; + RTIndexType type = IndexProperty_GetIndexType(hProp); + if (type == RT_InvalidIndexType ) { + Error_PushError(RT_Failure, + "Index type is not properly set", + "IndexProperty_SetIndexVariant"); + return RT_Failure; + } + if (type == RT_RTree) { + var.m_val.lVal = static_cast<RTree::RTreeVariant>(value); + prop->setProperty("TreeVariant", var); + } else if (type == RT_MVRTree) { + var.m_val.lVal = static_cast<MVRTree::MVRTreeVariant>(value); + prop->setProperty("TreeVariant", var); + } else if (type == RT_TPRTree) { + var.m_val.lVal = static_cast<TPRTree::TPRTreeVariant>(value); + prop->setProperty("TreeVariant", var); + } + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexVariant"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTIndexVariant IndexProperty_GetIndexVariant(IndexPropertyH hProp) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_GetIndexVariant", + RT_InvalidIndexVariant); + + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("TreeVariant"); + + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG) { + Error_PushError(RT_Failure, + "Property IndexVariant must be Tools::VT_LONG", + "IndexProperty_GetIndexVariant"); + return RT_InvalidIndexVariant; + } + + return static_cast<RTIndexVariant>(var.m_val.lVal); + } + + // if we didn't get anything, we're returning an error condition + Error_PushError(RT_Failure, + "Property IndexVariant was empty", + "IndexProperty_GetIndexVariant"); + return RT_InvalidIndexVariant; + +} + +SIDX_C_DLL RTError IndexProperty_SetIndexStorage( IndexPropertyH hProp, + RTStorageType value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexStorage", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (!(value == RT_Disk || value == RT_Memory || value == RT_Custom)) { + throw std::runtime_error("Inputted value is not a valid index storage type"); + } + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexStorageType", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexStorage"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexStorage"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexStorage"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL RTStorageType IndexProperty_GetIndexStorage(IndexPropertyH hProp) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_GetIndexStorage", + RT_InvalidStorageType); + + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexStorageType"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexStorage must be Tools::VT_ULONG", + "IndexProperty_GetIndexStorage"); + return RT_InvalidStorageType; + } + + return static_cast<RTStorageType>(var.m_val.ulVal); + } + + // if we didn't get anything, we're returning an error condition + Error_PushError(RT_Failure, + "Property IndexStorage was empty", + "IndexProperty_GetIndexStorage"); + return RT_InvalidStorageType; + +} + +SIDX_C_DLL RTError IndexProperty_SetIndexCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetIndexCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexCapacity must be Tools::VT_ULONG", + "IndexProperty_GetIndexCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property IndexCapacity was empty", + "IndexProperty_GetIndexCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetLeafCapacity( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetLeafCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("LeafCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetLeafCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetLeafCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetLeafCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetLeafCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetLeafCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("LeafCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property LeafCapacity must be Tools::VT_ULONG", + "IndexProperty_GetLeafCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property LeafCapacity was empty", + "IndexProperty_GetLeafCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetPagesize( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetPagesize", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("PageSize", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetPagesize"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetPagesize"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetPagesize"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetPagesize(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetPagesize", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("PageSize"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property PageSize must be Tools::VT_ULONG", + "IndexProperty_GetPagesize"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property PageSize was empty", + "IndexProperty_GetPagesize"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetLeafPoolCapacity( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetLeafPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("LeafPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetLeafPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetLeafPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetLeafPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetLeafPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetLeafPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("LeafPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property LeafPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetLeafPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property LeafPoolCapacity was empty", + "IndexProperty_GetLeafPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexPoolCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("IndexPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetIndexPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property IndexPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetIndexPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property IndexPoolCapacity was empty", + "IndexProperty_GetIndexPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetRegionPoolCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetRegionPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("RegionPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetRegionPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetRegionPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetRegionPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetRegionPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetRegionPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("RegionPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property RegionPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetRegionPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property RegionPoolCapacity was empty", + "IndexProperty_GetRegionPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetPointPoolCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetPointPoolCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("PointPoolCapacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetPointPoolCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetPointPoolCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetPointPoolCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetPointPoolCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetPointPoolCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("PointPoolCapacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property PointPoolCapacity must be Tools::VT_ULONG", + "IndexProperty_GetPointPoolCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property PointPoolCapacity was empty", + "IndexProperty_GetPointPoolCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetNearMinimumOverlapFactor( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetNearMinimumOverlapFactor", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("NearMinimumOverlapFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetNearMinimumOverlapFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetNearMinimumOverlapFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetNearMinimumOverlapFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetNearMinimumOverlapFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetNearMinimumOverlapFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("NearMinimumOverlapFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property NearMinimumOverlapFactor must be Tools::VT_ULONG", + "IndexProperty_GetNearMinimumOverlapFactor"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property NearMinimumOverlapFactor was empty", + "IndexProperty_GetNearMinimumOverlapFactor"); + return 0; +} + + +SIDX_C_DLL RTError IndexProperty_SetBufferingCapacity(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetBufferingCapacity", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("Capacity", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetBufferingCapacity"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetBufferingCapacity"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetBufferingCapacity"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetBufferingCapacity(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetBufferingCapacity", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Capacity"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property Capacity must be Tools::VT_ULONG", + "IndexProperty_GetBufferingCapacity"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property Capacity was empty", + "IndexProperty_GetBufferingCapacity"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetEnsureTightMBRs( IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetEnsureTightMBRs", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (value > 1 ) { + Error_PushError(RT_Failure, + "EnsureTightMBRs is a boolean value and must be 1 or 0", + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } + Tools::Variant var; + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = (bool)value; + prop->setProperty("EnsureTightMBRs", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetEnsureTightMBRs"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetEnsureTightMBRs(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetEnsureTightMBRs", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("EnsureTightMBRs"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) { + Error_PushError(RT_Failure, + "Property EnsureTightMBRs must be Tools::VT_BOOL", + "IndexProperty_GetEnsureTightMBRs"); + return 0; + } + + return var.m_val.blVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property EnsureTightMBRs was empty", + "IndexProperty_GetEnsureTightMBRs"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetWriteThrough(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetWriteThrough", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (value > 1 ) { + Error_PushError(RT_Failure, + "WriteThrough is a boolean value and must be 1 or 0", + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } + Tools::Variant var; + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = value; + prop->setProperty("WriteThrough", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetWriteThrough"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetWriteThrough(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetWriteThrough", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("WriteThrough"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) { + Error_PushError(RT_Failure, + "Property WriteThrough must be Tools::VT_BOOL", + "IndexProperty_GetWriteThrough"); + return 0; + } + + return var.m_val.blVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property WriteThrough was empty", + "IndexProperty_GetWriteThrough"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetOverwrite(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetOverwrite", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + if (value > 1 ) { + Error_PushError(RT_Failure, + "Overwrite is a boolean value and must be 1 or 0", + "IndexProperty_SetOverwrite"); + return RT_Failure; + } + Tools::Variant var; + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = value; + prop->setProperty("Overwrite", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetOverwrite"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetOverwrite"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetOverwrite"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetOverwrite(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetOverwrite", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Overwrite"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) { + Error_PushError(RT_Failure, + "Property Overwrite must be Tools::VT_BOOL", + "IndexProperty_GetOverwrite"); + return 0; + } + + return var.m_val.blVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property Overwrite was empty", + "IndexProperty_GetOverwrite"); + return 0; +} + + +SIDX_C_DLL RTError IndexProperty_SetFillFactor( IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetFillFactor", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("FillFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFillFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFillFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFillFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetFillFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFillFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FillFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property FillFactor must be Tools::VT_DOUBLE", + "IndexProperty_GetFillFactor"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FillFactor was empty", + "IndexProperty_GetFillFactor"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetSplitDistributionFactor( IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetSplitDistributionFactor", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("SplitDistributionFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetSplitDistributionFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetSplitDistributionFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetSplitDistributionFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetSplitDistributionFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetSplitDistributionFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("SplitDistributionFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property SplitDistributionFactor must be Tools::VT_DOUBLE", + "IndexProperty_GetSplitDistributionFactor"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property SplitDistributionFactor was empty", + "IndexProperty_GetSplitDistributionFactor"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetTPRHorizon(IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetTPRHorizon", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("Horizon", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetTPRHorizon"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetTPRHorizon"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetTPRHorizon"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetTPRHorizon(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetTPRHorizon", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("Horizon"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property Horizon must be Tools::VT_DOUBLE", + "IndexProperty_GetTPRHorizon"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property Horizon was empty", + "IndexProperty_GetTPRHorizon"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetReinsertFactor( IndexPropertyH hProp, + double value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetReinsertFactor", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = value; + prop->setProperty("ReinsertFactor", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetReinsertFactor"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetReinsertFactor"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetReinsertFactor"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL double IndexProperty_GetReinsertFactor(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetReinsertFactor", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("ReinsertFactor"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) { + Error_PushError(RT_Failure, + "Property ReinsertFactor must be Tools::VT_DOUBLE", + "IndexProperty_GetReinsertFactor"); + return 0; + } + + return var.m_val.dblVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property ReinsertFactor was empty", + "IndexProperty_GetReinsertFactor"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetFileName( IndexPropertyH hProp, + const char* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetFileName", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = STRDUP(value); // not sure if we should copy here + prop->setProperty("FileName", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFileName"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFileName"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFileName"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL char* IndexProperty_GetFileName(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFileName", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FileName"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) { + Error_PushError(RT_Failure, + "Property FileName must be Tools::VT_PCHAR", + "IndexProperty_GetFileName"); + return NULL; + } + + return STRDUP(var.m_val.pcVal); + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FileName was empty", + "IndexProperty_GetFileName"); + return NULL; +} + + +SIDX_C_DLL RTError IndexProperty_SetFileNameExtensionDat( IndexPropertyH hProp, + const char* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetFileNameExtensionDat", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = STRDUP(value); // not sure if we should copy here + prop->setProperty("FileNameDat", var); + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFileNameExtensionDat"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFileNameExtensionDat"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFileNameExtensionDat"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL char* IndexProperty_GetFileNameExtensionDat(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFileNameExtensionDat", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FileNameDat"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) { + Error_PushError(RT_Failure, + "Property FileNameDat must be Tools::VT_PCHAR", + "IndexProperty_GetFileNameExtensionDat"); + return NULL; + } + + return STRDUP(var.m_val.pcVal); + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FileNameDat was empty", + "IndexProperty_GetFileNameExtensionDat"); + return NULL; +} + +SIDX_C_DLL RTError IndexProperty_SetFileNameExtensionIdx( IndexPropertyH hProp, + const char* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetFileNameExtensionIdx", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = STRDUP(value); // not sure if we should copy here + prop->setProperty("FileNameIdx", var); + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetFileNameExtensionIdx"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetFileNameExtensionIdx"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetFileNameExtensionIdx"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL char* IndexProperty_GetFileNameExtensionIdx(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetFileNameExtensionIdx", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("FileNameIdx"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) { + Error_PushError(RT_Failure, + "Property FileNameIdx must be Tools::VT_PCHAR", + "IndexProperty_GetFileNameExtensionIdx"); + return NULL; + } + + return STRDUP(var.m_val.pcVal); + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property FileNameIdx was empty", + "IndexProperty_GetFileNameExtensionIdx"); + return NULL; +} + +SIDX_C_DLL RTError IndexProperty_SetCustomStorageCallbacksSize(IndexPropertyH hProp, + uint32_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetCustomStorageCallbacksSize", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = value; + prop->setProperty("CustomStorageCallbacksSize", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetCustomStorageCallbacksSize"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetCustomStorageCallbacksSize"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetCustomStorageCallbacksSize"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL uint32_t IndexProperty_GetCustomStorageCallbacksSize(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetCustomStorageCallbacksSize", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("CustomStorageCallbacksSize"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) { + Error_PushError(RT_Failure, + "Property CustomStorageCallbacksSize must be Tools::VT_ULONG", + "IndexProperty_GetCustomStorageCallbacksSize"); + return 0; + } + + return var.m_val.ulVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property CustomStorageCallbacksSize was empty", + "IndexProperty_GetCustomStorageCallbacksSize"); + return 0; +} + +SIDX_C_DLL RTError IndexProperty_SetCustomStorageCallbacks( IndexPropertyH hProp, + const void* value) +{ + VALIDATE_POINTER1( hProp, + "IndexProperty_SetCustomStorageCallbacks", + RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + // check if the CustomStorageCallbacksSize is alright, so we can make a copy of the passed in structure + Tools::Variant varSize; + varSize = prop->getProperty("CustomStorageCallbacksSize"); + if ( varSize.m_val.ulVal != sizeof(SpatialIndex::StorageManager::CustomStorageManagerCallbacks) ) + { + std::ostringstream ss; + ss << "The supplied storage callbacks size is wrong, expected " + << sizeof(SpatialIndex::StorageManager::CustomStorageManagerCallbacks) + << ", got " << varSize.m_val.ulVal; + Error_PushError(RT_Failure, + ss.str().c_str(), + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_PVOID; + var.m_val.pvVal = value ? + new SpatialIndex::StorageManager::CustomStorageManagerCallbacks( + *static_cast<const SpatialIndex::StorageManager::CustomStorageManagerCallbacks*>(value) + ) + : 0; + prop->setProperty("CustomStorageCallbacks", var); + + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetCustomStorageCallbacks"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL void* IndexProperty_GetCustomStorageCallbacks(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetCustomStorageCallbacks", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("CustomStorageCallbacks"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PVOID) { + Error_PushError(RT_Failure, + "Property CustomStorageCallbacks must be Tools::VT_PVOID", + "IndexProperty_GetCustomStorageCallbacks"); + return NULL; + } + + return var.m_val.pvVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property CustomStorageCallbacks was empty", + "IndexProperty_GetCustomStorageCallbacks"); + return NULL; +} + +SIDX_C_DLL RTError IndexProperty_SetIndexID(IndexPropertyH hProp, + int64_t value) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_SetIndexID", RT_Failure); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + try + { + Tools::Variant var; + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = value; + prop->setProperty("IndexIdentifier", var); + } catch (Tools::Exception& e) + { + Error_PushError(RT_Failure, + e.what().c_str(), + "IndexProperty_SetIndexID"); + return RT_Failure; + } catch (std::exception const& e) + { + Error_PushError(RT_Failure, + e.what(), + "IndexProperty_SetIndexID"); + return RT_Failure; + } catch (...) { + Error_PushError(RT_Failure, + "Unknown Error", + "IndexProperty_SetIndexID"); + return RT_Failure; + } + return RT_None; +} + +SIDX_C_DLL int64_t IndexProperty_GetIndexID(IndexPropertyH hProp) +{ + VALIDATE_POINTER1(hProp, "IndexProperty_GetIndexID", 0); + Tools::PropertySet* prop = static_cast<Tools::PropertySet*>(hProp); + + Tools::Variant var; + var = prop->getProperty("IndexIdentifier"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONGLONG) { + Error_PushError(RT_Failure, + "Property IndexIdentifier must be Tools::VT_LONGLONG", + "IndexProperty_GetIndexID"); + return 0; + } + + return var.m_val.llVal; + } + + // return nothing for an error + Error_PushError(RT_Failure, + "Property IndexIdentifier was empty", + "IndexProperty_GetIndexID"); + return 0; +} + +SIDX_C_DLL void* SIDX_NewBuffer(size_t length) +{ + return new char[length]; +} + +SIDX_C_DLL void SIDX_DeleteBuffer(void* buffer) +{ + delete []buffer; +} + + +SIDX_C_DLL char* SIDX_Version() +{ + + std::ostringstream ot; + +#ifdef SIDX_RELEASE_NAME + ot << SIDX_RELEASE_NAME; +#else + ot << "1.3.2"; +#endif + + std::string out(ot.str()); + return STRDUP(out.c_str()); + +} +IDX_C_END diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/all-wcprops new file mode 100644 index 000000000..870c8c628 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/all-wcprops @@ -0,0 +1,77 @@ +K 25 +svn:wc:ra_dav:version-url +V 57 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/mvrtree +END +Statistics.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/Statistics.h +END +PointerPoolNode.h +K 25 +svn:wc:ra_dav:version-url +V 75 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/PointerPoolNode.h +END +MVRTree.cc +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/mvrtree/MVRTree.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/45/spatialindex/trunk/src/mvrtree/Makefile.am +END +Node.cc +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/mvrtree/Node.cc +END +MVRTree.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/133/spatialindex/trunk/src/mvrtree/MVRTree.h +END +Index.cc +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/mvrtree/Index.cc +END +Leaf.cc +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/Leaf.cc +END +Node.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/Node.h +END +Index.h +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/Index.h +END +Leaf.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/Leaf.h +END +Statistics.cc +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/mvrtree/Statistics.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/dir-prop-base new file mode 100644 index 000000000..ea9b95e8a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/dir-prop-base @@ -0,0 +1,9 @@ +K 10 +svn:ignore +V 33 +Makefile.in +.libs +.deps +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/entries new file mode 100644 index 000000000..7578fc788 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/entries @@ -0,0 +1,436 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/mvrtree +http://svn.gispython.org/spatialindex + + + +2009-11-02T20:08:16.754818Z +159 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Statistics.h +file + + + + +2011-08-01T00:42:34.585398Z +46097afdf587be1e2946c68370a63c58 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2378 + +PointerPoolNode.h +file + + + + +2011-08-01T00:42:34.585398Z +28baf97a05d4debc58e4560ec41bb6da +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2788 + +MVRTree.cc +file + + + + +2011-08-01T00:42:34.585398Z +db395a4df8ffff429090625d6e9c3801 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +42471 + +Makefile.am +file + + + + +2011-08-01T00:42:34.585398Z +d9c9482e6c8fc615fa50b171bc4b519c +2008-01-17T23:34:01.575758Z +45 +hobu + + + + + + + + + + + + + + + + + + + + + +273 + +Node.cc +file + + + + +2011-08-01T00:42:34.585398Z +133b545522606cb58fc3decd6fe9d8de +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +45560 + +MVRTree.h +file + + + + +2011-08-01T00:42:34.589408Z +696b326d73b2b9882492dfd6c9532011 +2009-08-14T15:19:40.553411Z +133 +hobu + + + + + + + + + + + + + + + + + + + + + +7501 + +Index.cc +file + + + + +2011-08-01T00:42:34.589408Z +764bad93562eae7f748a4fb2cd8f24cc +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +12251 + +Leaf.cc +file + + + + +2011-08-01T00:42:34.617112Z +31d2b21592badd5cdd98748c86c230e0 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +3353 + +Node.h +file + + + + +2011-08-01T00:42:34.654108Z +0c92c89effd91685adc289817b5cd248 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +6069 + +Index.h +file + + + + +2011-08-01T00:42:34.654108Z +3d4f0e095cf33749ba3869a0ab7cf0a7 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2236 + +Leaf.h +file + + + + +2011-08-01T00:42:34.654108Z +c9fc6307581bd2bdfd33ee7ce084888c +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +1464 + +Statistics.cc +file + + + + +2011-08-01T00:42:34.654108Z +9e2c3dfd9b9c9bc027858a52a1660a27 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +4515 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Index.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Index.cc.svn-base new file mode 100644 index 000000000..ba5d0e113 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Index.cc.svn-base @@ -0,0 +1,429 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MVRTree.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" + +using namespace SpatialIndex::MVRTree; + +Index::~Index() +{ +} + +Index::Index(SpatialIndex::MVRTree::MVRTree* pTree, id_type id, uint32_t level) : Node(pTree, id, level, pTree->m_indexCapacity) +{ +} + +NodePtr Index::chooseSubtree(const TimeRegion& mbr, uint32_t insertionLevel, std::stack<id_type>& pathBuffer) +{ + if (m_level == insertionLevel) return NodePtr(this, &(m_pTree->m_indexPool)); + + pathBuffer.push(m_identifier); + + uint32_t child = 0; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + child = findLeastEnlargement(mbr); + break; + case RV_RSTAR: + if (m_level == 1) + { + // if this node points to leaves... + child = findLeastOverlap(mbr); + } + else + { + child = findLeastEnlargement(mbr); + } + break; + default: + throw Tools::NotSupportedException("Index::chooseSubtree: Tree variant not supported."); + } + assert (child != std::numeric_limits<uint32_t>::max()); + + NodePtr n = m_pTree->readNode(m_pIdentifier[child]); + NodePtr ret = n->chooseSubtree(mbr, insertionLevel, pathBuffer); + assert(n.unique()); + if (ret.get() == n.get()) n.relinquish(); + + return ret; +} + +NodePtr Index::findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // check live nodes only. + if (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max()) continue; + //if (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max() || + // m_ptrMBR[cChild]->m_startTime > mbr.m_startTime) continue; + + if (m_ptrMBR[cChild]->containsRegion(mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findLeaf(mbr, id, pathBuffer); + if (n.get() == l.get()) n.relinquish(); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} + +void Index::split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + default: + throw Tools::NotSupportedException("Index::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_indexPool.acquire(); + pRight = m_pTree->m_indexPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Index(m_pTree, m_identifier, m_level), &(m_pTree->m_indexPool)); + if (pRight.get() == 0) pRight = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(0, 0, *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(0, 0, *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + } +} + +uint32_t Index::findLeastEnlargement(const TimeRegion& r) const +{ + double area = std::numeric_limits<double>::max(); + uint32_t best = std::numeric_limits<uint32_t>::max(); + + TimeRegionPtr t = m_pTree->m_regionPool.acquire(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // if this child is already dead do not consider it. + if (m_ptrMBR[cChild]->m_endTime <= r.m_startTime) continue; + + m_ptrMBR[cChild]->getCombinedRegion(*t, r); + + double a = m_ptrMBR[cChild]->getArea(); + double enl = t->getArea() - a; + + if (enl < area) + { + area = enl; + best = cChild; + } + else if ( + enl > area - std::numeric_limits<double>::epsilon() && + enl < area + std::numeric_limits<double>::epsilon()) + { + if (a < m_ptrMBR[best]->getArea()) best = cChild; + } + } + +#ifndef NDEBUG + if (best == std::numeric_limits<uint32_t>::max()) + { + std::ostringstream s; + s << "findLeastEnlargement: All entries of node " << m_identifier << " are dead."; + throw Tools::IllegalStateException(s.str()); + } +#endif + + return best; +} + +uint32_t Index::findLeastOverlap(const TimeRegion& r) const +{ + OverlapEntry** entries = new OverlapEntry*[m_children]; + + double leastOverlap = std::numeric_limits<double>::max(); + double me = std::numeric_limits<double>::max(); + OverlapEntry* best = 0; + uint32_t cLiveEntries = 0; + + // find combined region and enlargement of every entry and store it. + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_ptrMBR[cChild]->m_endTime <= r.m_startTime) continue; + + try + { + entries[cLiveEntries] = new OverlapEntry(); + } + catch (...) + { + for (uint32_t i = 0; i < cLiveEntries; ++i) delete entries[i]; + delete[] entries; + throw; + } + + entries[cLiveEntries]->m_index = cChild; + entries[cLiveEntries]->m_original = m_ptrMBR[cChild]; + entries[cLiveEntries]->m_combined = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->getCombinedRegion(*(entries[cLiveEntries]->m_combined), r); + entries[cLiveEntries]->m_oa = entries[cLiveEntries]->m_original->getArea(); + entries[cLiveEntries]->m_ca = entries[cLiveEntries]->m_combined->getArea(); + entries[cLiveEntries]->m_enlargement = entries[cLiveEntries]->m_ca - entries[cLiveEntries]->m_oa; + + if (entries[cLiveEntries]->m_enlargement < me) + { + me = entries[cLiveEntries]->m_enlargement; + best = entries[cLiveEntries]; + } + else if (entries[cLiveEntries]->m_enlargement == me && entries[cLiveEntries]->m_oa < best->m_oa) + { + best = entries[cLiveEntries]; + } + ++cLiveEntries; + } + +#ifndef NDEBUG + if (cLiveEntries == 0) + { + std::ostringstream s; + s << "findLeastOverlap: All entries of node " << m_identifier << " are dead."; + throw Tools::IllegalStateException(s.str()); + } +#endif + + if (me < -std::numeric_limits<double>::epsilon() || me > std::numeric_limits<double>::epsilon()) + { + uint32_t cIterations; + + if (cLiveEntries > m_pTree->m_nearMinimumOverlapFactor) + { + // sort entries in increasing order of enlargement. + ::qsort(entries, cLiveEntries, + sizeof(OverlapEntry*), + OverlapEntry::compareEntries); + assert(entries[0]->m_enlargement <= entries[m_children - 1]->m_enlargement); + + cIterations = m_pTree->m_nearMinimumOverlapFactor; + } + else + { + cIterations = cLiveEntries; + } + + // calculate overlap of most important original entries (near minimum overlap cost). + for (uint32_t cIndex = 0; cIndex < cIterations; ++cIndex) + { + double dif = 0.0; + OverlapEntry* e = entries[cIndex]; + + for (uint32_t cChild = 0; cChild < cLiveEntries; ++cChild) + { + if (cIndex != cChild) + { + double f = e->m_combined->getIntersectingArea(*(entries[cChild]->m_original)); + if (f != 0.0) dif += f - e->m_original->getIntersectingArea(*(entries[cChild]->m_original)); + } + } // for (cChild) + + if (dif < leastOverlap) + { + leastOverlap = dif; + best = e; + } + else if (dif == leastOverlap) + { + if (e->m_enlargement == best->m_enlargement) + { + // keep the one with least area. + if (e->m_original->getArea() < best->m_original->getArea()) best = e; + } + else + { + // keep the one with least enlargement. + if (e->m_enlargement < best->m_enlargement) best = e; + } + } + } // for (cIndex) + } + + uint32_t ret = best->m_index; + + for (uint32_t cChild = 0; cChild < cLiveEntries; ++cChild) + { + delete entries[cChild]; + } + delete[] entries; + + return ret; +} + +void Index::adjustTree(Node* n, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n->m_identifier) break; + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + bool bContained = m_nodeMBR.containsRegion(n->m_nodeMBR); + bool bTouches = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool bRecompute = (! bContained || (bTouches && m_pTree->m_bTightMBRs)); + + // we should not adjust time here + double st = m_ptrMBR[child]->m_startTime; + double en = m_ptrMBR[child]->m_endTime; + *(m_ptrMBR[child]) = n->m_nodeMBR; + m_ptrMBR[child]->m_startTime = st; + m_ptrMBR[child]->m_endTime = en; + + if (bRecompute) + { + // no need to update times here. The inserted MBR is younger than all nodes. + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + m_pTree->writeNode(this); + + if (bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} + +void Index::adjustTree(Node* n, Node* nn, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child, child2 = m_capacity; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == nn->m_identifier) child2 = child; + if (m_pIdentifier[child] == n->m_identifier) break; + } + + if (child2 == m_capacity) + { + for (child2 = child + 1; child2 < m_children; ++child2) + { + if (m_pIdentifier[child2] == nn->m_identifier) break; + } + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + // 3. the SIBLING MBR is touching. + bool b1 = m_nodeMBR.containsRegion(n->m_nodeMBR); + bool b2 = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool b3 = m_nodeMBR.touchesRegion(*(m_ptrMBR[child2])); + bool bRecompute = (! b1) || ((b2 || b3) && m_pTree->m_bTightMBRs); + + // we should not adjust time here + double st = m_ptrMBR[child]->m_startTime; + double en = m_ptrMBR[child]->m_endTime; + *(m_ptrMBR[child]) = n->m_nodeMBR; + m_ptrMBR[child]->m_startTime = st; + m_ptrMBR[child]->m_endTime = en; + + st = m_ptrMBR[child2]->m_startTime; + en = m_ptrMBR[child2]->m_endTime; + *(m_ptrMBR[child2]) = nn->m_nodeMBR; + m_ptrMBR[child2]->m_startTime = st; + m_ptrMBR[child2]->m_endTime = en; + + if (bRecompute) + { + // no need to update times here. The inserted MBR is younger than all nodes. + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + m_pTree->writeNode(this); + + if (bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Index.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Index.h.svn-base new file mode 100644 index 000000000..e5fa86a8c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Index.h.svn-base @@ -0,0 +1,75 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class Index : public Node + { + public: + virtual ~Index(); + + private: + Index(MVRTree* pTree, id_type id, uint32_t level); + + virtual NodePtr chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& left, NodePtr& right, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + + uint32_t findLeastEnlargement(const TimeRegion&) const; + uint32_t findLeastOverlap(const TimeRegion&) const; + + void adjustTree(Node*, std::stack<id_type>&); + void adjustTree(Node* n, Node* nn, std::stack<id_type>& pathBuffer); + + class OverlapEntry + { + public: + uint32_t m_index; + double m_enlargement; + TimeRegionPtr m_original; + TimeRegionPtr m_combined; + double m_oa; + double m_ca; + + static int compareEntries(const void* pv1, const void* pv2) + { + OverlapEntry* pe1 = * (OverlapEntry**) pv1; + OverlapEntry* pe2 = * (OverlapEntry**) pv2; + + if (pe1->m_enlargement < pe2->m_enlargement) return -1; + if (pe1->m_enlargement > pe2->m_enlargement) return 1; + return 0; + } + }; // OverlapEntry + + friend class MVRTree; + friend class Node; + }; // Index + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Leaf.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Leaf.cc.svn-base new file mode 100644 index 000000000..925c170da --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Leaf.cc.svn-base @@ -0,0 +1,103 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MVRTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::MVRTree; + +Leaf::~Leaf() +{ +} + +Leaf::Leaf(SpatialIndex::MVRTree::MVRTree* pTree, id_type id): Node(pTree, id, 0, pTree->m_leafCapacity) +{ +} + +NodePtr Leaf::chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) +{ + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + return NodePtr(this, &(m_pTree->m_leafPool)); +} + +NodePtr Leaf::findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + if (m_pIdentifier[cChild] == id && static_cast<Region>(mbr) == static_cast<Region>(*(m_ptrMBR[cChild]))) + return NodePtr(this, &(m_pTree->m_leafPool)); + } + + return NodePtr(); +} + +void Leaf::split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + default: + throw Tools::NotSupportedException("Leaf::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_leafPool.acquire(); + pRight = m_pTree->m_leafPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + if (pRight.get() == 0) pRight = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(m_pDataLength[g1[cIndex]], m_pData[g1[cIndex]], *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g1[cIndex]] = 0; + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(m_pDataLength[g2[cIndex]], m_pData[g2[cIndex]], *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g2[cIndex]] = 0; + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Leaf.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Leaf.h.svn-base new file mode 100644 index 000000000..02d653c45 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Leaf.h.svn-base @@ -0,0 +1,48 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class Leaf : public Node + { + public: + virtual ~Leaf(); + + private: + Leaf(MVRTree* pTree, id_type id); + + virtual NodePtr chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& left, NodePtr& right, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + + friend class MVRTree; + friend class Node; + }; // Leaf + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/MVRTree.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/MVRTree.cc.svn-base new file mode 100644 index 000000000..7520e6689 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/MVRTree.cc.svn-base @@ -0,0 +1,1423 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" +#include "MVRTree.h" + +#include <cstring> + +using namespace SpatialIndex::MVRTree; + +SpatialIndex::MVRTree::Data::Data(uint32_t len, byte* pData, TimeRegion& r, id_type id) + : m_id(id), m_region(r), m_pData(0), m_dataLength(len) +{ + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, pData, m_dataLength); + } +} + +SpatialIndex::MVRTree::Data::~Data() +{ + delete[] m_pData; +} + +SpatialIndex::MVRTree::Data* SpatialIndex::MVRTree::Data::clone() +{ + return new Data(m_dataLength, m_pData, m_region, m_id); +} + +SpatialIndex::id_type SpatialIndex::MVRTree::Data::getIdentifier() const +{ + return m_id; +} + +void SpatialIndex::MVRTree::Data::getShape(IShape** out) const +{ + *out = new TimeRegion(m_region); +} + +void SpatialIndex::MVRTree::Data::getData(uint32_t& len, byte** data) const +{ + len = m_dataLength; + *data = 0; + + if (m_dataLength > 0) + { + *data = new byte[m_dataLength]; + memcpy(*data, m_pData, m_dataLength); + } +} + +uint32_t SpatialIndex::MVRTree::Data::getByteArraySize() +{ + return + sizeof(id_type) + + sizeof(uint32_t) + + m_dataLength + + m_region.getByteArraySize(); +} + +void SpatialIndex::MVRTree::Data::loadFromByteArray(const byte* ptr) +{ + memcpy(&m_id, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + delete[] m_pData; + m_pData = 0; + + memcpy(&m_dataLength, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, ptr, m_dataLength); + ptr += m_dataLength; + } + + m_region.loadFromByteArray(ptr); +} + +void SpatialIndex::MVRTree::Data::storeToByteArray(byte** data, uint32_t& len) +{ + // it is thread safe this way. + uint32_t regionsize; + byte* regiondata = 0; + m_region.storeToByteArray(®iondata, regionsize); + + len = sizeof(id_type) + sizeof(uint32_t) + m_dataLength + regionsize; + + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_id, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_dataLength, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + memcpy(ptr, m_pData, m_dataLength); + ptr += m_dataLength; + } + + memcpy(ptr, regiondata, regionsize); + delete[] regiondata; + // ptr += regionsize; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::MVRTree::returnMVRTree(SpatialIndex::IStorageManager& sm, Tools::PropertySet& ps) +{ + SpatialIndex::ISpatialIndex* si = new SpatialIndex::MVRTree::MVRTree(sm, ps); + return si; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::MVRTree::createNewMVRTree( + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + MVRTreeVariant rv, + id_type& indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = fillFactor; + ps.setProperty("FillFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = indexCapacity; + ps.setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = leafCapacity; + ps.setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = dimension; + ps.setProperty("Dimension", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = rv; + ps.setProperty("TreeVariant", var); + + ISpatialIndex* ret = returnMVRTree(sm, ps); + + var.m_varType = Tools::VT_LONGLONG; + var = ps.getProperty("IndexIdentifier"); + indexIdentifier = var.m_val.llVal; + + return ret; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::MVRTree::loadMVRTree(IStorageManager& sm, id_type indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = indexIdentifier; + ps.setProperty("IndexIdentifier", var); + + return returnMVRTree(sm, ps); +} + +SpatialIndex::MVRTree::MVRTree::MVRTree(IStorageManager& sm, Tools::PropertySet& ps) : + m_pStorageManager(&sm), + m_headerID(StorageManager::NewPage), + m_treeVariant(RV_RSTAR), + m_fillFactor(0.7), + m_indexCapacity(100), + m_leafCapacity(100), + m_nearMinimumOverlapFactor(32), + m_splitDistributionFactor(0.4), + m_reinsertFactor(0.3), + m_strongVersionOverflow(0.8), + //m_strongVersionUnderflow(0.2), + m_versionUnderflow(0.3), + m_dimension(2), + m_bTightMBRs(true), + m_bHasVersionCopied(false), + m_currentTime(0.0), + m_pointPool(500), + m_regionPool(1000), + m_indexPool(100), + m_leafPool(100) +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + + Tools::Variant var = ps.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType == Tools::VT_LONGLONG) m_headerID = var.m_val.llVal; + else if (var.m_varType == Tools::VT_LONG) m_headerID = var.m_val.lVal; + // for backward compatibility only. + else throw Tools::IllegalArgumentException("MVRTree: Property IndexIdentifier must be Tools::VT_LONGLONG"); + + initOld(ps); + } + else + { + initNew(ps); + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = m_headerID; + ps.setProperty("IndexIdentifier", var); + } +} + +SpatialIndex::MVRTree::MVRTree::~MVRTree() +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_destroy(&m_rwLock); +#endif + + storeHeader(); +} + +// +// ISpatialIndex interface +// + +void SpatialIndex::MVRTree::MVRTree::insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&shape); + if (ti == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IInterval interface."); + if (ti->getLowerBound() < m_currentTime) throw Tools::IllegalArgumentException("insertData: Shape start time is older than tree current time."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("insertData: cannot acquire an exclusive lock"); +#endif + + try + { + // convert the shape into a TimeRegion (R-Trees index regions only; i.e., approximations of the shapes). + Region mbrold; + shape.getMBR(mbrold); + + TimeRegionPtr mbr = m_regionPool.acquire(); + mbr->makeDimension(mbrold.m_dimension); + + memcpy(mbr->m_pLow, mbrold.m_pLow, mbrold.m_dimension * sizeof(double)); + memcpy(mbr->m_pHigh, mbrold.m_pHigh, mbrold.m_dimension * sizeof(double)); + mbr->m_startTime = ti->getLowerBound(); + mbr->m_endTime = std::numeric_limits<double>::max(); + + byte* buffer = 0; + + if (len > 0) + { + buffer = new byte[len]; + memcpy(buffer, pData, len); + } + + insertData_impl(len, buffer, *mbr, id); + // the buffer is stored in the tree. Do not delete here. + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +bool SpatialIndex::MVRTree::MVRTree::deleteData(const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("deleteData: Shape has the wrong number of dimensions."); + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&shape); + if (ti == 0) throw Tools::IllegalArgumentException("deleteData: Shape does not support the Tools::IInterval interface."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("deleteData: cannot acquire an exclusive lock"); +#endif + + try + { + Region mbrold; + shape.getMBR(mbrold); + + TimeRegionPtr mbr = m_regionPool.acquire(); + mbr->makeDimension(mbrold.m_dimension); + + memcpy(mbr->m_pLow, mbrold.m_pLow, mbrold.m_dimension * sizeof(double)); + memcpy(mbr->m_pHigh, mbrold.m_pHigh, mbrold.m_dimension * sizeof(double)); + mbr->m_startTime = ti->getLowerBound(); + mbr->m_endTime = ti->getUpperBound(); + + bool ret = deleteData_impl(*mbr, id); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + return ret; + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::containsWhatQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("containsWhatQuery: Shape has the wrong number of dimensions."); + rangeQuery(ContainmentQuery, query, v); +} + +void SpatialIndex::MVRTree::MVRTree::intersectsWithQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("intersectsWithQuery: Shape has the wrong number of dimensions."); + rangeQuery(IntersectionQuery, query, v); +} + +void SpatialIndex::MVRTree::MVRTree::pointLocationQuery(const Point& query, IVisitor& v) +{ + if (query.m_dimension != m_dimension) throw Tools::IllegalArgumentException("pointLocationQuery: Shape has the wrong number of dimensions."); + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&query); + if (ti == 0) throw Tools::IllegalArgumentException("pointLocationQuery: Shape does not support the Tools::IInterval interface."); + TimeRegion r(query, query, *ti); + rangeQuery(IntersectionQuery, r, v); +} + +void SpatialIndex::MVRTree::MVRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) +{ + throw Tools::IllegalStateException("nearestNeighborQuery: not impelmented yet."); +} + +void SpatialIndex::MVRTree::MVRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + NNComparator nnc; + nearestNeighborQuery(k, query, v, nnc); +} + +void SpatialIndex::MVRTree::MVRTree::selfJoinQuery(const IShape& query, IVisitor& v) +{ + throw Tools::IllegalStateException("selfJoinQuery: not impelmented yet."); +} + +void SpatialIndex::MVRTree::MVRTree::queryStrategy(IQueryStrategy& qs) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("queryStrategy: cannot acquire a shared lock"); +#endif + + id_type next = m_roots[m_roots.size() - 1].m_id; + bool hasNext = true; + + try + { + while (hasNext) + { + NodePtr n = readNode(next); + qs.getNextEntry(*n, next, hasNext); + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::getIndexProperties(Tools::PropertySet& out) const +{ + Tools::Variant var; + + // dimension + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_dimension; + out.setProperty("Dimension", var); + + // index capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexCapacity; + out.setProperty("IndexCapacity", var); + + // leaf capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafCapacity; + out.setProperty("LeafCapacity", var); + + // Tree variant + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = m_treeVariant; + out.setProperty("TreeVariant", var); + + // fill factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_fillFactor; + out.setProperty("FillFactor", var); + + // near minimum overlap factor + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_nearMinimumOverlapFactor; + out.setProperty("NearMinimumOverlapFactor", var); + + // split distribution factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_splitDistributionFactor; + out.setProperty("SplitDistributionFactor", var); + + // reinsert factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_reinsertFactor; + out.setProperty("ReinsertFactor", var); + + // tight MBRs + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = m_bTightMBRs; + out.setProperty("EnsureTightMBRs", var); + + // index pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexPool.getCapacity(); + out.setProperty("IndexPoolCapacity", var); + + // leaf pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafPool.getCapacity(); + out.setProperty("LeafPoolCapacity", var); + + // region pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_regionPool.getCapacity(); + out.setProperty("RegionPoolCapacity", var); + + // point pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_pointPool.getCapacity(); + out.setProperty("PointPoolCapacity", var); + + // strong version overflow + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_strongVersionOverflow; + out.setProperty("StrongVersionOverflow", var); + + // strong version underflow + //var.m_varType = Tools::VT_DOUBLE; + //var.m_val.dblVal = m_strongVersionUnderflow; + //out.setProperty("StrongVersionUnderflow", var); + + // weak version underflow + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_versionUnderflow; + out.setProperty("VersionUnderflow", var); +} + +void SpatialIndex::MVRTree::MVRTree::addCommand(ICommand* pCommand, CommandType ct) +{ + switch (ct) + { + case CT_NODEREAD: + m_readNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEWRITE: + m_writeNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEDELETE: + m_deleteNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + } +} + +bool SpatialIndex::MVRTree::MVRTree::isIndexValid() +{ + bool ret = true; + std::stack<ValidateEntry> st; + std::set<id_type> visitedEntries; + uint32_t degenerateEntries = 0; + + for (uint32_t cRoot = 0; cRoot < m_roots.size(); ++cRoot) + { + NodePtr root = readNode(m_roots[cRoot].m_id); + + if (root->m_level != m_stats.m_treeHeight[cRoot] - 1) + { + std::cerr << "Invalid tree height." << std::endl; + return false; + } + + ValidateEntry e(0, root->m_nodeMBR, root); + e.m_bIsDead = (root->m_nodeMBR.m_endTime < std::numeric_limits<double>::max()) ? true : false; + st.push(e); + } + + while (! st.empty()) + { + ValidateEntry e = st.top(); st.pop(); + + std::set<id_type>::iterator itSet = visitedEntries.find(e.m_pNode->m_identifier); + if (itSet == visitedEntries.end()) + { + visitedEntries.insert(e.m_pNode->m_identifier); + if (e.m_pNode->m_nodeMBR.m_startTime == e.m_pNode->m_nodeMBR.m_endTime) ++degenerateEntries; + } + + TimeRegion tmpRegion; + tmpRegion = m_infiniteRegion; + + for (uint32_t cDim = 0; cDim < tmpRegion.m_dimension; ++cDim) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + tmpRegion.m_pLow[cDim] = std::min(tmpRegion.m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pLow[cDim]); + tmpRegion.m_pHigh[cDim] = std::max(tmpRegion.m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + + tmpRegion.m_startTime = e.m_pNode->m_nodeMBR.m_startTime; + tmpRegion.m_endTime = e.m_pNode->m_nodeMBR.m_endTime; + if (! (tmpRegion == e.m_pNode->m_nodeMBR)) + { + std::cerr << "Invalid parent information." << std::endl; + ret = false; + } + + if (! e.m_bIsDead) + { + tmpRegion.m_startTime = e.m_parentMBR.m_startTime; + tmpRegion.m_endTime = e.m_parentMBR.m_endTime; + if (! (tmpRegion == e.m_parentMBR)) + { + std::cerr << "Error in parent (Node id: " << e.m_pNode->m_identifier << ", Parent id: " << e.m_parentID << ")." << std::endl; + ret = false; + } + } + + if (e.m_pNode->m_level != 0) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]); + + bool bIsDead = + (e.m_pNode->m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max() || e.m_bIsDead) ? true : false; + + // if the parent says that this child is dead, force it dead since + // this information is not propagated for efficiency and is inconsistent. + if (bIsDead) ptrN->m_nodeMBR.m_endTime = e.m_pNode->m_ptrMBR[cChild]->m_endTime; + + ValidateEntry tmpEntry(e.m_pNode->m_identifier, *(e.m_pNode->m_ptrMBR[cChild]), ptrN); + tmpEntry.m_bIsDead = bIsDead; + st.push(tmpEntry); + } + } + } + + //std::cerr << "Total accessible nodes: " << visitedEntries.size() << std::endl; + //std::cerr << "Degenerate nodes: " << degenerateEntries << std::endl; + + return ret; +} + +void SpatialIndex::MVRTree::MVRTree::getStatistics(IStatistics** out) const +{ + *out = new Statistics(m_stats); +} + +void SpatialIndex::MVRTree::MVRTree::initNew(Tools::PropertySet& ps) +{ + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG || (var.m_val.lVal != RV_LINEAR && var.m_val.lVal != RV_QUADRATIC && var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initNew: Property TreeVariant must be Tools::VT_LONG and of MVRTreeVariant type"); + + m_treeVariant = static_cast<MVRTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + //((m_treeVariant == RV_LINEAR || m_treeVariant == RV_QUADRATIC) && var.m_val.dblVal > 0.5) || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property FillFactor must be Tools::VT_DOUBLE and in (0.0, 1.0) for RSTAR, (0.0, 0.5) for LINEAR and QUADRATIC"); + + m_fillFactor = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 10) + throw Tools::IllegalArgumentException("initNew: Property IndexCapacity must be Tools::VT_ULONG and >= 10"); + + m_indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 10) + throw Tools::IllegalArgumentException("initNew: Property LeafCapacity must be Tools::VT_ULONG and >= 10"); + + m_leafCapacity = var.m_val.ulVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 1 || var.m_val.ulVal > m_indexCapacity || var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) throw Tools::IllegalArgumentException("initNew: Property Dimension must be greater than 1"); + + m_dimension = var.m_val.ulVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initNew: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + // strong version overflow + var = ps.getProperty("StrongVersionOverflow"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property StrongVersionOverflow must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_strongVersionOverflow = var.m_val.dblVal; + } + + // strong version underflow + //var = ps.getProperty("StrongVersionUnderflow"); + //if (var.m_varType != Tools::VT_EMPTY) + //{ + // if (var.m_varType != Tools::VT_DOUBLE || + // var.m_val.dblVal <= 0.0 || + // var.m_val.dblVal >= 1.0) throw Tools::IllegalArgumentException("Property StrongVersionUnderflow must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + // m_strongVersionUnderflow = var.m_val.dblVal; + //} + + // weak version underflow + var = ps.getProperty("VersionUnderflow"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property VersionUnderflow must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_versionUnderflow = var.m_val.dblVal; + } + + m_infiniteRegion.makeInfinite(m_dimension); + + m_stats.m_treeHeight.push_back(1); + m_stats.m_nodesInLevel.push_back(1); + + Leaf root(this, -1); + root.m_nodeMBR.m_startTime = 0.0; + root.m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + writeNode(&root); + m_roots.push_back(RootEntry(root.m_identifier, root.m_nodeMBR.m_startTime, root.m_nodeMBR.m_endTime)); + + storeHeader(); +} + +void SpatialIndex::MVRTree::MVRTree::initOld(Tools::PropertySet& ps) +{ + loadHeader(); + + // only some of the properties may be changed. + // the rest are just ignored. + + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG || (var.m_val.lVal != RV_LINEAR && var.m_val.lVal != RV_QUADRATIC && var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initOld: Property TreeVariant must be Tools::VT_LONG and of MVRTreeVariant type"); + + m_treeVariant = static_cast<MVRTreeVariant>(var.m_val.lVal); + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 1 || var.m_val.ulVal > m_indexCapacity || var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE ||var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initOld: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); +} + +void SpatialIndex::MVRTree::MVRTree::storeHeader() +{ + const uint32_t headerSize = + sizeof(uint32_t) + // size of m_roots + static_cast<uint32_t>(m_roots.size()) + * (sizeof(id_type) + 2 * sizeof(double)) + // m_roots + sizeof(MVRTreeVariant) + // m_treeVariant + sizeof(double)+ // m_fillFactor + sizeof(uint32_t) + // m_indexCapacity + sizeof(uint32_t) + // m_leafCapacity + sizeof(uint32_t) + // m_nearMinimumOverlapFactor + sizeof(double) + // m_splitDistributionFactor + sizeof(double) + // m_reinsertFactor + sizeof(uint32_t) + // m_dimension + sizeof(byte) + // m_bTightMBRs + sizeof(uint32_t) + // m_stats.m_nodes + sizeof(uint64_t) + // m_stats.m_totalData + sizeof(uint32_t) + // m_stats.m_deadIndexNodes + sizeof(uint32_t) + // m_stats.m_deadLeafNodes + sizeof(uint64_t) + // m_stats.m_data + sizeof(uint32_t) + // size of m_stats.m_treeHeight + static_cast<uint32_t>(m_stats.m_treeHeight.size()) + * sizeof(uint32_t) + // m_stats.m_treeHeight + sizeof(double) + // m_strongVersionOverflow + //sizeof(double) + // m_strongVersionUnderflow + sizeof(double) + // m_versionUnderflow + sizeof(double) + // m_currentTime + sizeof(uint32_t) + // m_nodesInLevel size + static_cast<uint32_t>(m_stats.m_nodesInLevel.size()) + * sizeof(uint32_t); // m_nodesInLevel values + + byte* header = new byte[headerSize]; + byte* ptr = header; + + uint32_t u32I = static_cast<uint32_t>(m_roots.size()); + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (size_t cIndex = 0; cIndex < m_roots.size(); ++cIndex) + { + RootEntry& e = m_roots[cIndex]; + memcpy(ptr, &(e.m_id), sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &(e.m_startTime), sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(e.m_endTime), sizeof(double)); + ptr += sizeof(double); + } + + memcpy(ptr, &m_treeVariant, sizeof(MVRTreeVariant)); + ptr += sizeof(MVRTreeVariant); + memcpy(ptr, &m_fillFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_indexCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_leafCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_nearMinimumOverlapFactor, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_splitDistributionFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_reinsertFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + byte c = (byte) m_bTightMBRs; + memcpy(ptr, &c, sizeof(byte)); + ptr += sizeof(byte); + memcpy(ptr, &(m_stats.m_u32Nodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u64TotalData), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(ptr, &(m_stats.m_u32DeadIndexNodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u32DeadLeafNodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u64Data), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + + u32I = static_cast<uint32_t>(m_stats.m_treeHeight.size()); + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (size_t cIndex = 0; cIndex < m_stats.m_treeHeight.size(); ++cIndex) + { + u32I = m_stats.m_treeHeight[cIndex]; + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + memcpy(ptr, &m_strongVersionOverflow, sizeof(double)); + ptr += sizeof(double); + //memcpy(ptr, &m_strongVersionUnderflow, sizeof(double)); + //ptr += sizeof(double); + memcpy(ptr, &m_versionUnderflow, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_currentTime, sizeof(double)); + ptr += sizeof(double); + + u32I = static_cast<uint32_t>(m_stats.m_nodesInLevel.size()); + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (size_t cLevel = 0; cLevel < m_stats.m_nodesInLevel.size(); ++cLevel) + { + u32I = m_stats.m_nodesInLevel[cLevel]; + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + m_pStorageManager->storeByteArray(m_headerID, headerSize, header); + + delete[] header; +} + +void SpatialIndex::MVRTree::MVRTree::loadHeader() +{ + uint32_t headerSize; + byte* header = 0; + m_pStorageManager->loadByteArray(m_headerID, headerSize, &header); + + byte* ptr = header; + + uint32_t rootsSize; + memcpy(&rootsSize, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cIndex = 0; cIndex < rootsSize; ++cIndex) + { + RootEntry e; + memcpy(&(e.m_id), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&(e.m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(e.m_endTime), ptr, sizeof(double)); + ptr += sizeof(double); + m_roots.push_back(e); + } + + memcpy(&m_treeVariant, ptr, sizeof(MVRTreeVariant)); + ptr += sizeof(MVRTreeVariant); + memcpy(&m_fillFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_indexCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_leafCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_nearMinimumOverlapFactor, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_splitDistributionFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_reinsertFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + byte c; + memcpy(&c, ptr, sizeof(byte)); + m_bTightMBRs = (c != 0); + ptr += sizeof(byte); + memcpy(&(m_stats.m_u32Nodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u64TotalData), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(&(m_stats.m_u32DeadIndexNodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u32DeadLeafNodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u64Data), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + + uint32_t treeHeightSize; + memcpy(&treeHeightSize, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cIndex = 0; cIndex < treeHeightSize; ++cIndex) + { + uint32_t u32I; + memcpy(&u32I, ptr, sizeof(uint32_t)); + m_stats.m_treeHeight.push_back(u32I); + ptr += sizeof(uint32_t); + } + + memcpy(&m_strongVersionOverflow, ptr, sizeof(double)); + ptr += sizeof(double); + //memcpy(&m_strongVersionUnderflow, ptr, sizeof(double)); + //ptr += sizeof(double); + memcpy(&m_versionUnderflow, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_currentTime, ptr, sizeof(double)); + ptr += sizeof(double); + + uint32_t nodesInLevelSize; + memcpy(&nodesInLevelSize, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < nodesInLevelSize; ++cLevel) + { + uint32_t u32I; + memcpy(&u32I, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + m_stats.m_nodesInLevel.push_back(u32I); + } + + delete[] header; +} + +void SpatialIndex::MVRTree::MVRTree::insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id) +{ + assert(mbr.getDimension() == m_dimension); + assert(m_currentTime <= mbr.m_startTime); + + std::stack<id_type> pathBuffer; + m_currentTime = mbr.m_startTime; + + NodePtr root = readNode(m_roots[m_roots.size() - 1].m_id); + NodePtr l = root->chooseSubtree(mbr, 0, pathBuffer); + + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mbr, id, pathBuffer, m_infiniteRegion, -1, false); + + ++(m_stats.m_u64Data); + ++(m_stats.m_u64TotalData); +} + +void SpatialIndex::MVRTree::MVRTree::insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, uint32_t level) +{ + assert(mbr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + + NodePtr root = readNode(m_roots[m_roots.size() - 1].m_id); + NodePtr l = root->chooseSubtree(mbr, level, pathBuffer); + + assert(l->m_level == level); + + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mbr, id, pathBuffer, m_infiniteRegion, -1, false); +} + +bool SpatialIndex::MVRTree::MVRTree::deleteData_impl(const TimeRegion& mbr, id_type id) +{ + assert(mbr.m_dimension == m_dimension); + + m_currentTime = mbr.m_endTime; + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_roots[m_roots.size() - 1].m_id); + NodePtr l = root->findLeaf(mbr, id, pathBuffer); + + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + + if (l.get() != 0) + { + l->deleteData(id, mbr.m_endTime, pathBuffer); + --(m_stats.m_u64Data); + return true; + } + + return false; +} + +SpatialIndex::id_type SpatialIndex::MVRTree::MVRTree::writeNode(Node* n) +{ + byte* buffer; + uint32_t dataLength; + n->storeToByteArray(&buffer, dataLength); + + id_type page; + if (n->m_identifier < 0) page = StorageManager::NewPage; + else page = n->m_identifier; + + try + { + m_pStorageManager->storeByteArray(page, dataLength, buffer); + delete[] buffer; + } + catch (InvalidPageException& e) + { + delete[] buffer; + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("writeNode: failed with Tools::InvalidPageException"); + } + + if (n->m_identifier < 0) + { + n->m_identifier = page; + ++(m_stats.m_u32Nodes); + } + + ++(m_stats.m_u64Writes); + + for (size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex) + { + m_writeNodeCommands[cIndex]->execute(*n); + } + + return page; +} + +SpatialIndex::MVRTree::NodePtr SpatialIndex::MVRTree::MVRTree::readNode(id_type id) +{ + uint32_t dataLength; + byte* buffer; + + try + { + m_pStorageManager->loadByteArray(id, dataLength, &buffer); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("readNode: failed with Tools::InvalidPageException"); + } + + try + { + uint32_t nodeType; + memcpy(&nodeType, buffer, sizeof(uint32_t)); + + NodePtr n; + + if (nodeType == PersistentIndex) n = m_indexPool.acquire(); + else if (nodeType == PersistentLeaf) n = m_leafPool.acquire(); + else throw Tools::IllegalStateException("readNode: failed reading the correct node type information"); + + if (n.get() == 0) + { + if (nodeType == PersistentIndex) n = NodePtr(new Index(this, -1, 0), &m_indexPool); + else if (nodeType == PersistentLeaf) n = NodePtr(new Leaf(this, -1), &m_leafPool); + } + + //n->m_pTree = this; + n->m_identifier = id; + n->loadFromByteArray(buffer); + + ++(m_stats.m_u64Reads); + + for (size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex) + { + m_readNodeCommands[cIndex]->execute(*n); + } + + delete[] buffer; + return n; + } + catch (...) + { + delete[] buffer; + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::deleteNode(Node* n) +{ + try + { + m_pStorageManager->deleteByteArray(n->m_identifier); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("deleteNode: failed with Tools::InvalidPageException"); + } + + --(m_stats.m_u32Nodes); + + for (size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex) + { + m_deleteNodeCommands[cIndex]->execute(*n); + } +} + +void SpatialIndex::MVRTree::MVRTree::rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v) +{ + // any shape that implements IInterval and IShape, can be used here. + // FIXME: I am not using ITimeShape yet, even though I should. + + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&query); + if (ti == 0) throw Tools::IllegalArgumentException("rangeQuery: Shape does not support the Tools::IInterval interface."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("rangeQuery: cannot acquire a shared lock"); +#endif + + try + { + std::set<id_type> visitedNodes; + std::set<id_type> visitedData; + std::stack<NodePtr> st; + std::vector<id_type> ids; + findRootIdentifiers(*ti, ids); + + for (size_t cRoot = 0; cRoot < ids.size(); ++cRoot) + { + NodePtr root = readNode(ids[cRoot]); + if (root->m_children > 0 && query.intersectsShape(root->m_nodeMBR)) st.push(root); + } + + while (! st.empty()) + { + NodePtr n = st.top(); st.pop(); + visitedNodes.insert(n->m_identifier); + + if (n->m_level == 0) + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (visitedData.find(n->m_pIdentifier[cChild]) != visitedData.end()) continue; + + bool b; + if (type == ContainmentQuery) b = (n->m_ptrMBR[cChild])->intersectsInterval(*ti) && query.containsShape(*(n->m_ptrMBR[cChild])); + else b = (n->m_ptrMBR[cChild])->intersectsInterval(*ti) && query.intersectsShape(*(n->m_ptrMBR[cChild])); + + if (b) + { + visitedData.insert(n->m_pIdentifier[cChild]); + Data data = Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + v.visitData(data); + ++(m_stats.m_u64QueryResults); + } + } + } + else + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if ( + visitedNodes.find(n->m_pIdentifier[cChild]) == visitedNodes.end() && + n->m_ptrMBR[cChild]->intersectsInterval(*ti) && + query.intersectsShape(*(n->m_ptrMBR[cChild]))) + st.push(readNode(n->m_pIdentifier[cChild])); + } + } + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::findRootIdentifiers(const Tools::IInterval& ti, std::vector<id_type>& ids) +{ + ids.clear(); + + for (size_t cRoot = 0; cRoot < m_roots.size(); ++cRoot) + { + RootEntry& e = m_roots[cRoot]; + if (ti.intersectsInterval(Tools::IT_RIGHTOPEN, e.m_startTime, e.m_endTime)) ids.push_back(e.m_id); + } +} + +std::string SpatialIndex::MVRTree::MVRTree::printRootInfo() const +{ + std::ostringstream s; + + for (size_t cRoot = 0; cRoot < m_roots.size(); ++cRoot) + { + const RootEntry& e = m_roots[cRoot]; + + s << "Root " << cRoot << ": Start " << e.m_startTime << ", End " << e.m_endTime << std::endl; + } + + return s.str(); +} + +std::ostream& SpatialIndex::MVRTree::operator<<(std::ostream& os, const MVRTree& t) +{ + os << "Dimension: " << t.m_dimension << std::endl + << "Fill factor: " << t.m_fillFactor << std::endl + << "Index capacity: " << t.m_indexCapacity << std::endl + << "Leaf capacity: " << t.m_leafCapacity << std::endl + << "Tight MBRs: " << ((t.m_bTightMBRs) ? "enabled" : "disabled") << std::endl; + + if (t.m_treeVariant == RV_RSTAR) + { + os << "Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl + << "Reinsert factor: " << t.m_reinsertFactor << std::endl + << "Split distribution factor: " << t.m_splitDistributionFactor << std::endl + << "Strong version overflow: " << t.m_strongVersionOverflow << std::endl + //<< "Strong version underflow: " << t.m_strongVersionUnderflow << std::endl + << "Weak version underflow: " << t.m_versionUnderflow << std::endl; + } + + // it is difficult to count utilization + //os << "Utilization: " << 100 * t.m_stats.m_totalData / (t.m_stats.getNumberOfNodesInLevel(0) * t.m_leafCapacity) << "%" << std::endl + + os << t.m_stats; + os << t.printRootInfo(); + + #ifndef NDEBUG + os << "Leaf pool hits: " << t.m_leafPool.m_hits << std::endl + << "Leaf pool misses: " << t.m_leafPool.m_misses << std::endl + << "Index pool hits: " << t.m_indexPool.m_hits << std::endl + << "Index pool misses: " << t.m_indexPool.m_misses << std::endl + << "Region pool hits: " << t.m_regionPool.m_hits << std::endl + << "Region pool misses: " << t.m_regionPool.m_misses << std::endl + << "Point pool hits: " << t.m_pointPool.m_hits << std::endl + << "Point pool misses: " << t.m_pointPool.m_misses << std::endl; + #endif + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/MVRTree.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/MVRTree.h.svn-base new file mode 100644 index 000000000..cfbe33c1e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/MVRTree.h.svn-base @@ -0,0 +1,222 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Statistics.h" +#include "Node.h" +#include "PointerPoolNode.h" + +namespace SpatialIndex +{ + namespace MVRTree + { + class MVRTree : public ISpatialIndex + { + class NNEntry; + class RootEntry; + + public: + MVRTree(IStorageManager&, Tools::PropertySet&); + // String Value Description + // ---------------------------------------------- + // IndexIndentifier VT_LONG If specified an existing index will be openened from the supplied + // storage manager with the given index id. Behaviour is unspecified + // if the index id or the storage manager are incorrect. + // Dimension VT_ULONG Dimensionality of the data that will be inserted. + // IndexCapacity VT_ULONG The index node capacity. Default is 100. + // LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. + // FillFactor VT_DOUBLE The fill factor. Default is 70% + // TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar + // NearMinimumOverlapFactor VT_ULONG Default is 32. + // SplitDistributionFactor VT_DOUBLE Default is 0.4 + // ReinsertFactor VT_DOUBLE Default is 0.3 + // EnsureTightMBRs VT_BOOL Default is true + // IndexPoolCapacity VT_LONG Default is 100 + // LeafPoolCapacity VT_LONG Default is 100 + // RegionPoolCapacity VT_LONG Default is 1000 + // PointPoolCapacity VT_LONG Default is 500 + // StrongVersionOverflow VT_DOUBLE Default is 0.8 + // VersionUnderflow VT_DOUBLE Default is 0.3 + + virtual ~MVRTree(); + + // + // ISpatialIndex interface + // + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id); + virtual bool deleteData(const IShape& shape, id_type id); + virtual void containsWhatQuery(const IShape& query, IVisitor& v); + virtual void intersectsWithQuery(const IShape& query, IVisitor& v); + virtual void pointLocationQuery(const Point& query, IVisitor& v); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator&); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v); + virtual void selfJoinQuery(const IShape& s, IVisitor& v); + virtual void queryStrategy(IQueryStrategy& qs); + virtual void getIndexProperties(Tools::PropertySet& out) const; + virtual void addCommand(ICommand* pCommand, CommandType ct); + virtual bool isIndexValid(); + virtual void getStatistics(IStatistics** out) const; + + private: + void initNew(Tools::PropertySet&); + void initOld(Tools::PropertySet& ps); + void storeHeader(); + void loadHeader(); + + void insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id); + void insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, uint32_t level); + bool deleteData_impl(const TimeRegion& mbr, id_type id); + + id_type writeNode(Node*); + NodePtr readNode(id_type id); + void deleteNode(Node* n); + + void rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v); + + void findRootIdentifiers(const Tools::IInterval& ti, std::vector<id_type>& ids); + std::string printRootInfo() const; + + IStorageManager* m_pStorageManager; + + std::vector<RootEntry> m_roots; + id_type m_headerID; + + MVRTreeVariant m_treeVariant; + + double m_fillFactor; + + uint32_t m_indexCapacity; + + uint32_t m_leafCapacity; + + uint32_t m_nearMinimumOverlapFactor; + // The R*-Tree 'p' constant, for calculating nearly minimum overlap cost. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles, Section 4.1] + + double m_splitDistributionFactor; + // The R*-Tree 'm' constant, for calculating spliting distributions. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles, Section 4.2] + + double m_reinsertFactor; + // The R*-Tree 'p' constant, for removing entries at reinserts. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles, Section 4.3] + + double m_strongVersionOverflow; + //double m_strongVersionUnderflow; + double m_versionUnderflow; + + uint32_t m_dimension; + + TimeRegion m_infiniteRegion; + + SpatialIndex::MVRTree::Statistics m_stats; + + bool m_bTightMBRs; + + bool m_bHasVersionCopied; + + double m_currentTime; + + Tools::PointerPool<Point> m_pointPool; + Tools::PointerPool<TimeRegion> m_regionPool; + Tools::PointerPool<Node> m_indexPool; + Tools::PointerPool<Node> m_leafPool; + + std::vector<Tools::SmartPointer<ICommand> > m_writeNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_readNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_deleteNodeCommands; + +#ifdef HAVE_PTHREAD_H + pthread_rwlock_t m_rwLock; +#else + bool m_rwLock; +#endif + + class RootEntry + { + public: + RootEntry() {} + RootEntry(id_type id, double s, double e) : m_id(id), m_startTime(s), m_endTime(e) {} + + id_type m_id; + double m_startTime; + double m_endTime; + }; // RootEntry + + class NNEntry + { + public: + id_type m_id; + IEntry* m_pEntry; + double m_minDist; + + NNEntry(id_type id, IEntry* e, double f) : m_id(id), m_pEntry(e), m_minDist(f) {} + ~NNEntry() {} + + struct greater : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_minDist > __y->m_minDist; } + }; + }; // NNEntry + + class NNComparator : public INearestNeighborComparator + { + public: + double getMinimumDistance(const IShape& query, const IShape& entry) + { + return query.getMinimumDistance(entry); + } + double getMinimumDistance(const IShape& query, const IData& data) + { + IShape* pR; + data.getShape(&pR); + double ret = query.getMinimumDistance(*pR); + delete pR; + return ret; + } + }; // NNComparator + + class ValidateEntry + { + public: + ValidateEntry(id_type pid, TimeRegion& r, NodePtr& pNode) : m_parentID(pid), m_parentMBR(r), m_pNode(pNode), m_bIsDead(false) {} + + id_type m_parentID; + TimeRegion m_parentMBR; + NodePtr m_pNode; + bool m_bIsDead; + }; // ValidateEntry + + friend class Node; + friend class Leaf; + friend class Index; + + friend std::ostream& operator<<(std::ostream& os, const MVRTree& t); + }; // MVRTree + + std::ostream& operator<<(std::ostream& os, const MVRTree& t); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..8c28ebe12 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libmvrtree.la +INCLUDES = -I../../include +libmvrtree_la_SOURCES = Index.cc Leaf.cc Node.cc MVRTree.cc Statistics.cc Index.h Leaf.h MVRTree.h Node.h PointerPoolNode.h Statistics.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Node.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Node.cc.svn-base new file mode 100644 index 000000000..b69e665c2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Node.cc.svn-base @@ -0,0 +1,1512 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MVRTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::MVRTree; + +// +// Tools::IObject interface +// +Tools::IObject* Node::clone() +{ + throw Tools::NotSupportedException("IObject::clone should never be called."); +} + +// +// Tools::ISerializable interface +// +uint32_t Node::getByteArraySize() +{ + return + (sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(double) + + sizeof(double) + + (m_children * (m_pTree->m_dimension * sizeof(double) * 2 + sizeof(id_type) + 2 * sizeof(double) + sizeof(uint32_t))) + + m_totalDataLength + + (2 * m_pTree->m_dimension * sizeof(double))); +} + +void Node::loadFromByteArray(const byte* ptr) +{ + m_nodeMBR = m_pTree->m_infiniteRegion; + + // skip the node type information, it is not needed. + ptr += sizeof(uint32_t); + + memcpy(&m_level, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&m_children, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&(m_nodeMBR.m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(m_nodeMBR.m_endTime), ptr, sizeof(double)); + ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_ptrMBR[cChild] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[cChild]) = m_pTree->m_infiniteRegion; + + memcpy(m_ptrMBR[cChild]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(&(m_pIdentifier[cChild]), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&(m_ptrMBR[cChild]->m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(m_ptrMBR[cChild]->m_endTime), ptr, sizeof(double)); + ptr += sizeof(double); + + memcpy(&(m_pDataLength[cChild]), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + m_totalDataLength += m_pDataLength[cChild]; + m_pData[cChild] = new byte[m_pDataLength[cChild]]; + memcpy(m_pData[cChild], ptr, m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + else + { + m_pData[cChild] = 0; + } + + //m_nodeMBR.combineRegion(*(m_ptrMBR[cChild])); + } + + memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +void Node::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + + *data = new byte[len]; + byte* ptr = *data; + + uint32_t nodeType; + + if (m_level == 0) nodeType = PersistentLeaf; + else nodeType = PersistentIndex; + + memcpy(ptr, &nodeType, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_level, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_children, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &(m_nodeMBR.m_startTime), sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(m_nodeMBR.m_endTime), sizeof(double)); + ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + memcpy(ptr, m_ptrMBR[cChild]->m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, &(m_pIdentifier[cChild]), sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &(m_ptrMBR[cChild]->m_startTime), sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(m_ptrMBR[cChild]->m_endTime), sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, &(m_pDataLength[cChild]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + memcpy(ptr, m_pData[cChild], m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + } + + // store the node MBR for efficiency. This increases the node size a little bit. + memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +// +// SpatialIndex::IEntry interface +// +SpatialIndex::id_type Node::getIdentifier() const +{ + return m_identifier; +} + +void Node::getShape(IShape** out) const +{ + *out = new TimeRegion(m_nodeMBR); +} + +// +// SpatialIndex::INode interface +// +uint32_t Node::getChildrenCount() const +{ + return m_children; +} + +SpatialIndex::id_type Node::getChildIdentifier(uint32_t index) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + return m_pIdentifier[index]; +} + +void Node::getChildShape(uint32_t index, IShape** out) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + *out = new TimeRegion(*(m_ptrMBR[index])); +} + + +void Node::getChildData(uint32_t index, uint32_t& length, byte** data) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + if (m_pData[index] == NULL) + { + length = 0; + data = NULL; + } + else + { + length = m_pDataLength[index]; + *data = m_pData[index]; + } +} + +uint32_t Node::getLevel() const +{ + return m_level; +} + +bool Node::isLeaf() const +{ + return (m_level == 0); +} + +bool Node::isIndex() const +{ + return (m_level != 0); +} + +// +// Internal +// + +Node::Node() : + m_pTree(0), + m_level(0), + m_identifier(-1), + m_children(0), + m_capacity(0), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ +} + + Node::Node(SpatialIndex::MVRTree::MVRTree* pTree, id_type id, uint32_t level, uint32_t capacity) : + m_pTree(pTree), + m_level(level), + m_identifier(id), + m_children(0), + m_capacity(capacity), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ + m_nodeMBR.makeInfinite(m_pTree->m_dimension); + + try + { + m_pDataLength = new uint32_t[m_capacity + 2]; + m_pData = new byte*[m_capacity + 2]; + m_ptrMBR = new TimeRegionPtr[m_capacity + 2]; + m_pIdentifier = new id_type[m_capacity + 2]; + } + catch (...) + { + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + throw; + } +} + +Node::~Node() +{ + if (m_pData != 0) + { + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_pData[cChild] != 0) delete[] m_pData[cChild]; + } + + delete[] m_pData; + delete[] m_pDataLength; + } + + if (m_ptrMBR != 0) delete[] m_ptrMBR; + if (m_pIdentifier != 0) delete[] m_pIdentifier; +} + +Node& Node::operator=(const Node& n) +{ + throw Tools::IllegalStateException("operator =: This should never be called."); +} + +void Node::insertEntry(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id) +{ + assert(m_children < m_capacity); + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + m_totalDataLength += dataLength; + ++m_children; + + m_nodeMBR.combineRegionInTime(mbr); +} + +bool Node::deleteEntry(uint32_t index) +{ + assert(index >= 0 && index < m_children); + + // cache it, since I might need it for "touches" later. + TimeRegionPtr ptrR = m_ptrMBR[index]; + + m_totalDataLength -= m_pDataLength[index]; + if (m_pData[index] != 0) delete[] m_pData[index]; + + if (m_children > 1 && index != m_children - 1) + { + m_pDataLength[index] = m_pDataLength[m_children - 1]; + m_pData[index] = m_pData[m_children - 1]; + m_ptrMBR[index] = m_ptrMBR[m_children - 1]; + m_pIdentifier[index] = m_pIdentifier[m_children - 1]; + } + + --m_children; + + // WARNING: index has now changed. Do not use it below here. + + if (m_children == 0) + { + m_nodeMBR = m_pTree->m_infiniteRegion; + return true; + } + else if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesShape(*ptrR)) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + return true; + } + + return false; +} + +bool Node::insertData( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2, bool bForceAdjust) +{ + // we should be certain that when bInsertMbr2 is true the node needs to be version split + + // this function returns true only if the node under modification has been stored (writeNode(this)) + // it is needed since some times after a version copy we do not need to actually store the node. Only + // the parent has to be notified to modify the entry pointing + // to this node with the appropriate deletion time (thus we save one disk access) + + if ((! bInsertMbr2) && m_children < m_capacity) + { + // the node has empty space. Insert the entry here + + // this has to happen before insertEntry modifies m_nodeMBR. + bool b = m_nodeMBR.containsShape(mbr); + + insertEntry(dataLength, pData, mbr, id); + m_pTree->writeNode(this); + + // a forced adjust might be needed when a child has modified it MBR due to an entry deletion + // (when the entry start time becomes equal to the entry end time after a version copy) + if ((! b || bForceAdjust) && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } + + return true; + } + else + { + // do a version copy + + bool bIsRoot = pathBuffer.empty(); + + NodePtr ptrCopy; + + // copy live entries of this node into a new node. Create an index or a leaf respectively + if (m_level == 0) + { + ptrCopy = m_pTree->m_leafPool.acquire(); + if (ptrCopy.get() == 0) ptrCopy = NodePtr(new Leaf(m_pTree, - 1), &(m_pTree->m_leafPool)); + else ptrCopy->m_nodeMBR = m_pTree->m_infiniteRegion; + } + else + { + ptrCopy = m_pTree->m_indexPool.acquire(); + if (ptrCopy.get() == 0) ptrCopy = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + else + { + ptrCopy->m_level = m_level; + ptrCopy->m_nodeMBR = m_pTree->m_infiniteRegion; + } + } + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (! (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max())) + { + byte* data = 0; + + if (m_pDataLength[cChild] > 0) + { + data = new byte[m_pDataLength[cChild]]; + memcpy(data, m_pData[cChild], m_pDataLength[cChild] * sizeof(byte)); + } + ptrCopy->insertEntry(m_pDataLength[cChild], data, *(m_ptrMBR[cChild]), m_pIdentifier[cChild]); + ptrCopy->m_ptrMBR[ptrCopy->m_children - 1]->m_startTime = mbr.m_startTime; + } + } + + ptrCopy->m_nodeMBR.m_startTime = mbr.m_startTime; + m_nodeMBR.m_endTime = mbr.m_startTime; + + uint32_t children = (bInsertMbr2) ? ptrCopy->m_children + 2 : ptrCopy->m_children + 1; + assert(children > 0); + + if (children >= m_pTree->m_strongVersionOverflow * m_capacity) + { + // strong version overflow. Split! + NodePtr n; + NodePtr nn; + ptrCopy->split(dataLength, pData, mbr, id, n, nn, mbr2, id2, bInsertMbr2); + assert(n->m_children > 1 && nn->m_children > 1); + + if (bIsRoot) + { + // it is a root node. Special handling required. + n->m_level = ptrCopy->m_level; + nn->m_level = ptrCopy->m_level; + n->m_identifier = -1; + nn->m_identifier = -1; + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + NodePtr ptrR = m_pTree->m_indexPool.acquire(); + if (ptrR.get() == 0) ptrR = NodePtr(new Index(m_pTree, -1, ptrCopy->m_level + 1), &(m_pTree->m_indexPool)); + else + { + //ptrR->m_pTree = m_pTree; + //ptrR->m_identifier = -1; + ptrR->m_level = ptrCopy->m_level + 1; + ptrR->m_nodeMBR = m_pTree->m_infiniteRegion; + } + + ptrR->insertEntry(0, 0, n->m_nodeMBR, n->m_identifier); + ptrR->insertEntry(0, 0, nn->m_nodeMBR, nn->m_identifier); + + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + ptrR->m_identifier = m_identifier; + m_pTree->writeNode(ptrR.get()); + m_pTree->m_stats.m_treeHeight[m_pTree->m_stats.m_treeHeight.size() - 1] = ptrR->m_level + 1; + m_pTree->m_stats.m_nodesInLevel.at(n->m_level) = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 1; + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime == ptrCopy->m_nodeMBR.m_startTime && + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime == ptrCopy->m_nodeMBR.m_endTime); + } + else + { + m_pTree->writeNode(this); + m_pTree->writeNode(ptrR.get()); + + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_id == m_identifier); + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime = m_nodeMBR.m_startTime; + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime = m_nodeMBR.m_endTime; + m_pTree->m_roots.push_back(MVRTree::RootEntry(ptrR->m_identifier, ptrR->m_nodeMBR.m_startTime, ptrR->m_nodeMBR.m_endTime)); + m_pTree->m_stats.m_treeHeight.push_back(ptrR->m_level + 1); + m_pTree->m_stats.m_nodesInLevel.at(n->m_level) = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 2; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + } + + if (ptrR->m_level >= m_pTree->m_stats.m_nodesInLevel.size()) m_pTree->m_stats.m_nodesInLevel.push_back(1); + else m_pTree->m_stats.m_nodesInLevel.at(ptrR->m_level) = m_pTree->m_stats.m_nodesInLevel[ptrR->m_level] + 1; + + return true; + } + else + { + bool b = false; + + n->m_level = ptrCopy->m_level; + nn->m_level = ptrCopy->m_level; +/* + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + n->m_identifier = m_identifier; + m_pTree->m_stats.m_nodesInLevel[n->m_level] = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 1; + b = true; + } + else + { + n->m_identifier = -1; + m_pTree->m_stats.m_nodesInLevel[n->m_level] = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 2; + } +*/ + n->m_identifier = -1; + nn->m_identifier = -1; + + m_pTree->m_stats.m_nodesInLevel.at(n->m_level) = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 2; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + ++(m_pTree->m_stats.m_u64Adjustments); + + // this is the special insertion function for two new nodes, defined below + p->insertData(n->m_nodeMBR, n->m_identifier, nn->m_nodeMBR, nn->m_identifier, this, pathBuffer); + + return b; + } + } + //else if (children < m_pTree->m_strongVersionUnderflow * m_capacity) + //{ + // do not do this for now + //} + else + { + // the entry contains the appropriate number of live entries + + ptrCopy->insertEntry(dataLength, pData, mbr, id); + if (bInsertMbr2) ptrCopy->insertEntry(0, 0, mbr2, id2); + + if (bIsRoot) + { + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + ptrCopy->m_identifier = m_identifier; + m_pTree->writeNode(ptrCopy.get()); + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime == ptrCopy->m_nodeMBR.m_startTime && + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime == ptrCopy->m_nodeMBR.m_endTime); + } + else + { + m_pTree->writeNode(ptrCopy.get()); + m_pTree->writeNode(this); + + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_id == m_identifier); + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime = m_nodeMBR.m_startTime; + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime = m_nodeMBR.m_endTime; + m_pTree->m_roots.push_back(MVRTree::RootEntry(ptrCopy->m_identifier, ptrCopy->m_nodeMBR.m_startTime, ptrCopy->m_nodeMBR.m_endTime)); + m_pTree->m_stats.m_treeHeight.push_back(ptrCopy->m_level + 1); + + m_pTree->m_stats.m_nodesInLevel.at(ptrCopy->m_level) = m_pTree->m_stats.m_nodesInLevel[ptrCopy->m_level] + 1; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + } + + return true; + } + else + { + m_pTree->writeNode(ptrCopy.get()); + + m_pTree->m_stats.m_nodesInLevel.at(ptrCopy->m_level) = m_pTree->m_stats.m_nodesInLevel[ptrCopy->m_level] + 1; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + ++(m_pTree->m_stats.m_u64Adjustments); + + uint32_t child; + for (child = 0; child < p->m_children; ++child) + { + if (p->m_pIdentifier[child] == m_identifier) break; + } + + // it might be needed to update the MBR since the child MBR might have changed + // from an entry deletion (from insertData, below, when m_startTime == m_endTime) + double st = p->m_ptrMBR[child]->m_startTime; + *(p->m_ptrMBR[child]) = m_nodeMBR; + p->m_ptrMBR[child]->m_startTime = st; + //p->m_ptrMBR[child]->m_endTime = mbr.m_startTime; + + // insert this new version copy into the parent + p->insertData(0, 0, ptrCopy->m_nodeMBR, ptrCopy->m_identifier, pathBuffer, m_pTree->m_infiniteRegion, -1, false); + + return false; + } + } + } +} + +void Node::insertData(TimeRegion& mbr1, id_type id1, TimeRegion& mbr2, id_type id2, Node* oldVersion, std::stack<id_type>& pathBuffer) +{ + // this should be called only from insertData above + // it tries to fit two new entries into the node + + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == oldVersion->m_identifier) break; + } + + // save the original node MBR + bool bAdjust = false; + TimeRegionPtr ptrR = m_pTree->m_regionPool.acquire(); + *ptrR = m_nodeMBR; + + // it might be needed to update the MBR since the child MBR might have changed + // from an entry deletion (when m_startTime == m_endTime) + double st = m_ptrMBR[child]->m_startTime; + *(m_ptrMBR[child]) = oldVersion->m_nodeMBR; + m_ptrMBR[child]->m_startTime = st; + //m_ptrMBR[child]->m_endTime = oldVersion->m_nodeMBR.m_endTime; + + if (m_children < m_capacity - 1) + { + // there is enough space for both new entries + + insertEntry(0, 0, mbr1, id1); + insertEntry(0, 0, mbr2, id2); + + m_pTree->writeNode(this); + + if ((! pathBuffer.empty()) && (bAdjust || ! (ptrR->containsShape(mbr1) && ptrR->containsShape(mbr2)))) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } + } + else + { + // call a normal insertData which will trigger a version copy + // insertData will adjust the parent since this node will certainly do a version copy + bool bStored = insertData(0, 0, mbr1, id1, pathBuffer, mbr2, id2, true); + if (! bStored) m_pTree->writeNode(this); + } +} + +bool Node::deleteData(id_type id, double delTime, std::stack<id_type>& pathBuffer, bool bForceAdjust) +{ + // it returns true if a new root has been created because all the entries of the old root have died. + // This is needed in case the root dies while there are pending reinsertions from multiple levels + + uint32_t child = m_capacity; + uint32_t alive = 0; + bool bAdjustParent = false; + TimeRegionPtr oldNodeMBR = m_pTree->m_regionPool.acquire(); + *oldNodeMBR = m_nodeMBR; + NodePtr parent; + + // make sure that there are no "snapshot" entries + // find how many children are alive and locate the entry to be deleted + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_level != 0 || (m_ptrMBR[cChild]->m_startTime != m_ptrMBR[cChild]->m_endTime)); + if (! (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max())) ++alive; + if (m_pIdentifier[cChild] == id) child = cChild; + } + + assert(child < m_capacity); + + // either make the entry dead or, if its start time is equal to the deletion time, + // delete it from the node completely (in which case the parent MBR might need adjustment) + bool bAdjusted = false; + + if (m_level == 0 && m_ptrMBR[child]->m_startTime == delTime) + { + bAdjusted = deleteEntry(child); + bAdjustParent = bAdjusted; + } + else + { + m_ptrMBR[child]->m_endTime = delTime; + } + + // if it has not been adjusted yet (by deleteEntry) and it should be adjusted, do it. + // a forced adjustment is needed when a child node has adjusted its own MBR and signals + // the parent to adjust it, also. + if ((! bAdjusted) && bForceAdjust) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + // signal our parent to adjust its MBR also + bAdjustParent = true; + } + + // one less live entry from now on + --alive; + + if (alive < m_pTree->m_versionUnderflow * m_capacity && (! pathBuffer.empty())) + { + // if the weak version condition is broken, try to resolve it + // if this is a leaf and it can still hold some entries (since all entries might be dead now and + // the node full) try to borrow a live entry from a sibling + // [Yufei Tao, Dimitris Papadias, 'MV3R-Tree: A Spatio-Temporal Access Method for Timestamp and + // Interval Queries', Section 3.3] + if (m_level == 0 && m_children < m_capacity) + { + parent = m_pTree->readNode(pathBuffer.top()); + pathBuffer.pop(); + + // find us in our parent + for (child = 0; child < parent->m_children; ++child) + { + if (parent->m_pIdentifier[child] == m_identifier) break; + } + + // remember that the parent might be younger than us, pointing to us through a pointer + // created with a version copy. So the actual start time of this node through the path + // from the root might actually be different than the stored start time. + double actualNodeStartTime = parent->m_ptrMBR[child]->m_startTime; + + // find an appropriate sibling + for (uint32_t cSibling = 0; cSibling < parent->m_children; ++cSibling) + { + // it has to be different than us, it has to be alive and its MBR should intersect ours + if ( + parent->m_pIdentifier[cSibling] != m_identifier && + ! (parent->m_ptrMBR[cSibling]->m_endTime < std::numeric_limits<double>::max()) && + parent->m_ptrMBR[cSibling]->intersectsShape(m_nodeMBR)) + { + NodePtr sibling = m_pTree->readNode(parent->m_pIdentifier[cSibling]); + std::vector<DeleteDataEntry> toCheck; + alive = 0; + + // if this child does not have a single parent, we cannot borrow an entry. + bool bSingleParent = true; + + for (uint32_t cSiblingChild = 0; cSiblingChild < sibling->m_children; ++cSiblingChild) + { + // if the insertion time of any child is smaller than the starting time stored in the + // parent of this node than the node has more than one parent + if (sibling->m_ptrMBR[cSiblingChild]->m_startTime < parent->m_ptrMBR[cSibling]->m_startTime) + { + bSingleParent = false; + break; + } + + // find the live sibling entries, and also the ones that can be moved to this node + // sort them by area enlargement + if (! (sibling->m_ptrMBR[cSiblingChild]->m_endTime < std::numeric_limits<double>::max())) + { + ++alive; + if (sibling->m_ptrMBR[cSiblingChild]->m_startTime >= actualNodeStartTime) + { + TimeRegionPtr tmpR = m_pTree->m_regionPool.acquire(); + *tmpR = m_nodeMBR; + tmpR->combineRegion(*(sibling->m_ptrMBR[cSiblingChild])); + double a = tmpR->getArea(); + if (a <= m_nodeMBR.getArea() * 1.1) toCheck.push_back(DeleteDataEntry(cSiblingChild, a)); + } + } + } + + // if the sibling has more than one parent or if we cannot remove an entry because we will + // cause a weak version overflow, this sibling is not appropriate + if ((! bSingleParent) || toCheck.empty() || alive == m_pTree->m_versionUnderflow * sibling->m_capacity + 1) continue; + + // create interval counters for checking weak version condition + // [Yufei Tao, Dimitris Papadias, 'MV3R-Tree: A Spatio-Temporal Access Method for Timestamp and + // Interval Queries', Section 3.2] + std::set<double> Si; + for (uint32_t cSiblingChild = 0; cSiblingChild < sibling->m_children; ++cSiblingChild) + { + Si.insert(sibling->m_ptrMBR[cSiblingChild]->m_startTime); + Si.insert(sibling->m_ptrMBR[cSiblingChild]->m_endTime); + } + // duplicate entries have been removed and the set is sorted + uint32_t* SiCounts = new uint32_t[Si.size() - 1]; + bzero(SiCounts, (Si.size() - 1) * sizeof(uint32_t)); + + for (uint32_t cSiblingChild = 0; cSiblingChild < sibling->m_children; ++cSiblingChild) + { + std::set<double>::iterator it1 = Si.begin(); + std::set<double>::iterator it2 = Si.begin(); + for (size_t cIndex = 0; cIndex < Si.size() - 1; ++cIndex) + { + ++it2; + if ( + sibling->m_ptrMBR[cSiblingChild]->m_startTime <= *it1 && + sibling->m_ptrMBR[cSiblingChild]->m_endTime >= *it2 + ) ++(SiCounts[cIndex]); + ++it1; + } + } + + std::vector<DeleteDataEntry> Sdel; + + for (size_t cCheck = 0; cCheck < toCheck.size(); ++cCheck) + { + bool good = true; + + // check if it can be removed without a weak version underflow + std::set<double>::iterator it1 = Si.begin(); + std::set<double>::iterator it2 = Si.begin(); + for (size_t cIndex = 0; cIndex < Si.size() - 1; ++cIndex) + { + ++it2; + if ( + sibling->m_ptrMBR[toCheck[cCheck].m_index]->m_startTime <= *it1 && + sibling->m_ptrMBR[toCheck[cCheck].m_index]->m_endTime >= *it2 && + SiCounts[cIndex] <= m_pTree->m_versionUnderflow * sibling->m_capacity) + { + good = false; + break; + } + ++it1; + } + if (good) Sdel.push_back(toCheck[cCheck]); + } + + delete[] SiCounts; + + if (Sdel.empty()) continue; + + // we found some entries. Sort them according to least enlargement, insert the best entry into + // this node, remove it from the sibling and update the MBRs of the parent + + sort(Sdel.begin(), Sdel.end(), DeleteDataEntry::compare); + uint32_t entry = Sdel[0].m_index; + bool b1 = m_nodeMBR.containsShape(*(sibling->m_ptrMBR[entry])); + bool b2 = sibling->m_nodeMBR.touchesShape(*(sibling->m_ptrMBR[entry])); + + insertEntry(sibling->m_pDataLength[entry], sibling->m_pData[entry], *(sibling->m_ptrMBR[entry]), sibling->m_pIdentifier[entry]); + sibling->m_pData[entry] = 0; + + // the weak version condition check above, guarantees that. + assert(sibling->m_children > 1); + sibling->deleteEntry(entry); + + m_pTree->writeNode(this); + m_pTree->writeNode(sibling.get()); + + Index* p = static_cast<Index*>(parent.get()); + if (((! b1) || bAdjustParent) && b2) p->adjustTree(this, sibling.get(), pathBuffer); + else if ((! b1) || bAdjustParent) p->adjustTree(this, pathBuffer); + else if (b2) p->adjustTree(sibling.get(), pathBuffer); + + return false; + } + } + } + + // either this is not a leaf, or an appropriate sibling was not found, so make this node dead + // and reinsert all live entries from the root + m_nodeMBR.m_endTime = delTime; + m_pTree->writeNode(this); + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + if (parent.get() == 0) + { + parent = m_pTree->readNode(pathBuffer.top()); + pathBuffer.pop(); + } + + if (bAdjustParent) + { + // the correct child pointer might have been calculated already from earlier + if (child < parent->m_children && m_identifier != parent->m_pIdentifier[child]) + { + for (child = 0; child < parent->m_children; ++child) + { + if (parent->m_pIdentifier[child] == m_identifier) break; + } + } + + // both start time and end time should be preserved since deleteData below needs + // to know how many entries where alive, including this one + double st = parent->m_ptrMBR[child]->m_startTime; + double en = parent->m_ptrMBR[child]->m_endTime; + *(parent->m_ptrMBR[child]) = m_nodeMBR; + parent->m_ptrMBR[child]->m_startTime = st; + parent->m_ptrMBR[child]->m_endTime = en; + } + + // delete this node from the parent node. + // if this node had been adjusted and its old MBR was touching the parent MBR, the + // parent MBR needs to be adjusted also. + // the deletion has to happen first, since the reinsertions might modify the path to this node + bool bNewRoot = parent->deleteData(m_identifier, delTime, pathBuffer, (bAdjustParent && parent->m_nodeMBR.touchesShape(*oldNodeMBR))); + + // reinsert all the live entries from the root + + // normally I should not modify any node instances, since writeNode might be caching nodes + // in main memory, even though I have persisted them, so I have to make copies + + // this code will try and reinsert whole paths if possible. It might be the case, though, + // that a root died, which means that all the live data entries have to be scanned and reinserted themselves + for (child = 0; child < m_children; ++child) + { + if (! (m_ptrMBR[child]->m_endTime < std::numeric_limits<double>::max())) + { + if (! bNewRoot || m_level == 0) + { + m_ptrMBR[child]->m_startTime = delTime; + m_pTree->insertData_impl(m_pDataLength[child], m_pData[child], *(m_ptrMBR[child]), m_pIdentifier[child], m_level); + // make sure we do not delete the data array from this node's destructor + m_pData[child] = 0; + } + else + { + std::stack<NodePtr> Sins; + Sins.push(m_pTree->readNode(m_pIdentifier[child])); + while (! Sins.empty()) + { + NodePtr p = Sins.top(); Sins.pop(); + if (p->m_level == 0) + { + for (uint32_t cIndex= 0; cIndex < p->m_children; ++cIndex) + { + if (! (p->m_ptrMBR[cIndex]->m_endTime < std::numeric_limits<double>::max())) + { + p->m_ptrMBR[cIndex]->m_startTime = delTime; + m_pTree->insertData_impl(p->m_pDataLength[cIndex], p->m_pData[cIndex], *(p->m_ptrMBR[cIndex]), p->m_pIdentifier[cIndex], p->m_level); + // make sure we do not delete the data array from this node's destructor + p->m_pData[cIndex] = 0; + } + } + } + else + { + for (uint32_t cIndex= 0; cIndex < p->m_children; ++cIndex) + { + if (! (p->m_ptrMBR[cIndex]->m_endTime < std::numeric_limits<double>::max())) + { + Sins.push(m_pTree->readNode(p->m_pIdentifier[cIndex])); + } + } + } + } + } + } + } + } + else + { + // either this is a root node or there is no weak version condition + + if (alive == 0 && pathBuffer.empty()) + { + if (m_children > 0) + { + // all root children are dead. Create a new root + m_nodeMBR.m_endTime = delTime; + m_pTree->m_bHasVersionCopied = false; + + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + Leaf root(m_pTree, m_identifier); + root.m_nodeMBR.m_startTime = m_nodeMBR.m_endTime; + root.m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + m_pTree->writeNode(&root); + + m_pTree->m_stats.m_treeHeight[m_pTree->m_stats.m_treeHeight.size() - 1] = 1; + if (m_pTree->m_stats.m_nodesInLevel.at(m_level) == 1) m_pTree->m_stats.m_nodesInLevel.pop_back(); + else m_pTree->m_stats.m_nodesInLevel.at(m_level) = m_pTree->m_stats.m_nodesInLevel[m_level] - 1; + m_pTree->m_stats.m_nodesInLevel.at(0) = m_pTree->m_stats.m_nodesInLevel[0] + 1; + } + else + { + m_pTree->writeNode(this); + + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + Leaf root(m_pTree, -1); + root.m_nodeMBR.m_startTime = m_nodeMBR.m_endTime; + root.m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + m_pTree->writeNode(&root); + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_id == m_identifier); + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime = m_nodeMBR.m_startTime; + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime = m_nodeMBR.m_endTime; + m_pTree->m_roots.push_back(MVRTree::RootEntry(root.m_identifier, root.m_nodeMBR.m_startTime, root.m_nodeMBR.m_endTime)); + + m_pTree->m_stats.m_treeHeight.push_back(1); + m_pTree->m_stats.m_nodesInLevel.at(root.m_level) = m_pTree->m_stats.m_nodesInLevel[root.m_level] + 1; + } + return true; + } + else + { + assert(m_level == 0); + m_pTree->writeNode(this); + m_pTree->m_bHasVersionCopied = false; + return false; + } + } + else if (bAdjustParent && (! pathBuffer.empty())) + { + // the parent needs to be adjusted + m_pTree->writeNode(this); + parent = m_pTree->readNode(pathBuffer.top()); + pathBuffer.pop(); + Index* p = static_cast<Index*>(parent.get()); + p->adjustTree(this, pathBuffer); + } + else + { + m_pTree->writeNode(this); + } + } + + return false; +} + +void Node::rtreeSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + uint32_t cChild; + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + uint32_t cTotal = (bInsertMbr2) ? m_children + 2 : m_children + 1; + + // use this mask array for marking visited entries. + byte* mask = new byte[cTotal]; + bzero(mask, cTotal); + + // insert new data in the node for easier manipulation. Data arrays are always + // by two larger than node capacity. + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + if (bInsertMbr2) + { + m_pDataLength[m_children + 1] = 0; + m_pData[m_children + 1] = 0; + m_ptrMBR[m_children + 1] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children + 1]) = mbr2; + m_pIdentifier[m_children + 1] = id2; + } + + // initialize each group with the seed entries. + uint32_t seed1, seed2; + pickSeeds(seed1, seed2, cTotal); + + group1.push_back(seed1); + group2.push_back(seed2); + + mask[seed1] = 1; + mask[seed2] = 1; + + // find MBR of each group. + TimeRegionPtr mbrA = m_pTree->m_regionPool.acquire(); + *mbrA = *(m_ptrMBR[seed1]); + TimeRegionPtr mbrB = m_pTree->m_regionPool.acquire(); + *mbrB = *(m_ptrMBR[seed2]); + + // count how many entries are left unchecked (exclude the seeds here.) + uint32_t cRemaining = cTotal - 2; + + while (cRemaining > 0) + { + if (minimumLoad - group1.size() == cRemaining) + { + // all remaining entries must be assigned to group1 to comply with minimun load requirement. + for (cChild = 0; cChild < cTotal; ++cChild) + { + if (mask[cChild] == 0) + { + group1.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else if (minimumLoad - group2.size() == cRemaining) + { + // all remaining entries must be assigned to group2 to comply with minimun load requirement. + for (cChild = 0; cChild < cTotal; ++cChild) + { + if (mask[cChild] == 0) + { + group2.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else + { + // For all remaining entries compute the difference of the cost of grouping an + // entry in either group. When done, choose the entry that yielded the maximum + // difference. In case of linear split, select any entry (e.g. the first one.) + uint32_t sel; + double md1 = 0.0, md2 = 0.0; + double m = -std::numeric_limits<double>::max(); + double d1, d2, d; + double a1 = mbrA->getArea(); + double a2 = mbrB->getArea(); + + TimeRegionPtr a = m_pTree->m_regionPool.acquire(); + TimeRegionPtr b = m_pTree->m_regionPool.acquire(); + + for (cChild = 0; cChild < cTotal; ++cChild) + { + if (mask[cChild] == 0) + { + mbrA->getCombinedRegion(*a, *(m_ptrMBR[cChild])); + d1 = a->getArea() - a1; + mbrB->getCombinedRegion(*b, *(m_ptrMBR[cChild])); + d2 = b->getArea() - a2; + d = std::abs(d1 - d2); + + if (d > m) + { + m = d; + md1 = d1; md2 = d2; + sel = cChild; + if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break; + } + } + } + + // determine the group where we should add the new entry. + int32_t group = 1; + + if (md1 < md2) + { + group1.push_back(sel); + group = 1; + } + else if (md2 < md1) + { + group2.push_back(sel); + group = 2; + } + else if (a1 < a2) + { + group1.push_back(sel); + group = 1; + } + else if (a2 < a1) + { + group2.push_back(sel); + group = 2; + } + else if (group1.size() < group2.size()) + { + group1.push_back(sel); + group = 1; + } + else if (group2.size() < group1.size()) + { + group2.push_back(sel); + group = 2; + } + else + { + group1.push_back(sel); + group = 1; + } + mask[sel] = 1; + --cRemaining; + if (group == 1) + { + mbrA->combineRegion(*(m_ptrMBR[sel])); + } + else + { + mbrB->combineRegion(*(m_ptrMBR[sel])); + } + } + } + + delete[] mask; +} + +void Node::rstarSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + RstarSplitEntry** dataLow = 0; + RstarSplitEntry** dataHigh = 0; + + uint32_t cTotal = (bInsertMbr2) ? m_children + 2 : m_children + 1; + + try + { + dataLow = new RstarSplitEntry*[cTotal]; + dataHigh = new RstarSplitEntry*[cTotal]; + } + catch (...) + { + delete[] dataLow; + throw; + } + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + if (bInsertMbr2) + { + m_pDataLength[m_children + 1] = 0; + m_pData[m_children + 1] = 0; + m_ptrMBR[m_children + 1] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children + 1]) = mbr2; + m_pIdentifier[m_children + 1] = id2; + } + + uint32_t nodeSPF = static_cast<uint32_t>(std::floor(cTotal * m_pTree->m_splitDistributionFactor)); + uint32_t splitDistribution = cTotal - (2 * nodeSPF) + 2; + + uint32_t cChild = 0, cDim, cIndex; + + for (cChild = 0; cChild < cTotal; ++cChild) + { + try + { + dataLow[cChild] = new RstarSplitEntry(m_ptrMBR[cChild].get(), cChild, 0); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete dataLow[i]; + delete[] dataLow; + delete[] dataHigh; + throw; + } + + dataHigh[cChild] = dataLow[cChild]; + } + + double minimumMargin = std::numeric_limits<double>::max(); + uint32_t splitAxis = std::numeric_limits<uint32_t>::max(); + uint32_t sortOrder = std::numeric_limits<uint32_t>::max(); + + // chooseSplitAxis. + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + ::qsort(dataLow, + cTotal, + sizeof(RstarSplitEntry*), + RstarSplitEntry::compareLow); + + ::qsort(dataHigh, + cTotal, + sizeof(RstarSplitEntry*), + RstarSplitEntry::compareHigh); + + // calculate sum of margins and overlap for all distributions. + double marginl = 0.0; + double marginh = 0.0; + + TimeRegion bbl1, bbl2, bbh1, bbh2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bbl1 = *(dataLow[0]->m_pRegion); + bbh1 = *(dataHigh[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bbl1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh1.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + bbl2 = *(dataLow[l]->m_pRegion); + bbh2 = *(dataHigh[l]->m_pRegion); + + for (cIndex = l + 1; cIndex < cTotal; ++cIndex) + { + bbl2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh2.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + marginl += bbl1.getMargin() + bbl2.getMargin(); + marginh += bbh1.getMargin() + bbh2.getMargin(); + } // for (cChild) + + double margin = std::min(marginl, marginh); + + // keep minimum margin as split axis. + if (margin < minimumMargin) + { + minimumMargin = margin; + splitAxis = cDim; + sortOrder = (marginl < marginh) ? 0 : 1; + } + + // increase the dimension according to which the data entries should be sorted. + for (cChild = 0; cChild < cTotal; ++cChild) + { + dataLow[cChild]->m_sortDim = cDim + 1; + } + } // for (cDim) + + for (cChild = 0; cChild < cTotal; ++cChild) + { + dataLow[cChild]->m_sortDim = splitAxis; + } + + ::qsort( + dataLow, + cTotal, + sizeof(RstarSplitEntry*), + (sortOrder == 0) ? RstarSplitEntry::compareLow : RstarSplitEntry::compareHigh); + + double ma = std::numeric_limits<double>::max(); + double mo = std::numeric_limits<double>::max(); + uint32_t splitPoint = std::numeric_limits<uint32_t>::max(); + + TimeRegion bb1, bb2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bb1 = *(dataLow[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bb1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + bb2 = *(dataLow[l]->m_pRegion); + + for (cIndex = l + 1; cIndex < cTotal; ++cIndex) + { + bb2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + double o = bb1.getIntersectingArea(bb2); + + if (o < mo) + { + splitPoint = cChild; + mo = o; + ma = bb1.getArea() + bb2.getArea(); + } + else if (o == mo) + { + double a = bb1.getArea() + bb2.getArea(); + + if (a < ma) + { + splitPoint = cChild; + ma = a; + } + } + } // for (cChild) + + uint32_t l1 = nodeSPF - 1 + splitPoint; + + for (cIndex = 0; cIndex < l1; ++cIndex) + { + group1.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + for (cIndex = l1; cIndex < cTotal; ++cIndex) + { + group2.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + delete[] dataLow; + delete[] dataHigh; +} + +void Node::pickSeeds(uint32_t& index1, uint32_t& index2, uint32_t total) +{ + double separation = -std::numeric_limits<double>::max(); + double inefficiency = -std::numeric_limits<double>::max(); + uint32_t cDim, cChild, cIndex; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_RSTAR: + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + double leastLower = m_ptrMBR[0]->m_pLow[cDim]; + double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim]; + uint32_t greatestLower = 0; + uint32_t leastUpper = 0; + double width; + + for (cChild = 1; cChild < total; ++cChild) + { + if (m_ptrMBR[cChild]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = cChild; + if (m_ptrMBR[cChild]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = cChild; + + leastLower = std::min(m_ptrMBR[cChild]->m_pLow[cDim], leastLower); + greatestUpper = std::max(m_ptrMBR[cChild]->m_pHigh[cDim], greatestUpper); + } + + width = greatestUpper - leastLower; + if (width <= 0) width = 1; + + double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width; + + if (f > separation) + { + index1 = leastUpper; + index2 = greatestLower; + separation = f; + } + } // for (cDim) + + if (index1 == index2) + { + if (index2 == 0) ++index2; + else --index2; + } + + break; + case RV_QUADRATIC: + // for each pair of Regions (account for overflow Region too!) + for (cChild = 0; cChild < total - 1; ++cChild) + { + double a = m_ptrMBR[cChild]->getArea(); + + for (cIndex = cChild + 1; cIndex < total; ++cIndex) + { + // get the combined MBR of those two entries. + TimeRegion r; + m_ptrMBR[cChild]->getCombinedRegion(r, *(m_ptrMBR[cIndex])); + + // find the inefficiency of grouping these entries together. + double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea(); + + if (d > inefficiency) + { + inefficiency = d; + index1 = cChild; + index2 = cIndex; + } + } // for (cIndex) + } // for (cChild) + + break; + default: + throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported."); + } +} + +NodePtr Node::findNode(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_pIdentifier[cChild] == id) + return m_pTree->readNode(m_pIdentifier[cChild]); + + if (m_ptrMBR[cChild]->containsShape(mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findNode(mbr, id, pathBuffer); + assert(n.get() != l.get()); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Node.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Node.h.svn-base new file mode 100644 index 000000000..187435e43 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Node.h.svn-base @@ -0,0 +1,184 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class MVRTree; + class Leaf; + class Index; + class Node; + + typedef Tools::PoolPointer<Node> NodePtr; + + class Node : public SpatialIndex::INode + { + public: + virtual ~Node(); + + // + // Tools::IObject interface + // + virtual IObject* clone(); + + // + // Tools::ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // SpatialIndex::IEntry interface + // + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + + // + // SpatialIndex::INode interface + // + virtual uint32_t getChildrenCount() const; + virtual id_type getChildIdentifier(uint32_t index) const; + virtual void getChildShape(uint32_t index, IShape** out) const; + virtual void getChildData(uint32_t index, uint32_t& length, byte** data) const; + virtual uint32_t getLevel() const; + virtual bool isIndex() const; + virtual bool isLeaf() const; + + private: + Node(); + Node(MVRTree* pTree, id_type id, uint32_t level, uint32_t capacity); + + virtual Node& operator=(const Node&); + + virtual void insertEntry(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id); + virtual bool deleteEntry(uint32_t index); + + virtual bool insertData( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false, bool forceAdjust = false); + virtual void insertData(TimeRegion& mbr1, id_type id1, TimeRegion& mbr2, id_type id2, Node* oldVersion, std::stack<id_type>& pathBuffer); + virtual bool deleteData(id_type id, double delTime, std::stack<id_type>& pathBuffer, bool adjustMBR = false); + + virtual void rtreeSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + virtual void rstarSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + + virtual void pickSeeds(uint32_t& index1, uint32_t& index2, uint32_t total); + + virtual NodePtr chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findNode(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& left, NodePtr& right, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false) = 0; + + MVRTree* m_pTree; + // Parent of all nodes. + + uint32_t m_level; + // The level of the node in the tree. + // Leaves are always at level 0. + + id_type m_identifier; + // The unique ID of this node. + + uint32_t m_children; + // The number of children pointed by this node. + + uint32_t m_capacity; + // Specifies the node capacity. + + TimeRegion m_nodeMBR; + // The minimum bounding region enclosing all data contained in the node. + + byte** m_pData; + // The data stored in the node. + + TimeRegionPtr* m_ptrMBR; + // The corresponding data MBRs. + + id_type* m_pIdentifier; + // The corresponding data identifiers. + + uint32_t* m_pDataLength; + + uint32_t m_totalDataLength; + + class RstarSplitEntry + { + public: + RstarSplitEntry(TimeRegion* pr, uint32_t index, uint32_t dimension) : + m_pRegion(pr), m_index(index), m_sortDim(dimension) {} + + static int compareLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] < pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] > pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return 1; + return 0; + } + + static int compareHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return 1; + return 0; + } + + TimeRegion* m_pRegion; + uint32_t m_index; + uint32_t m_sortDim; + }; // RstarSplitEntry + + class DeleteDataEntry + { + public: + DeleteDataEntry(uint32_t index, double d) : m_index(index), m_increase(d) {} + + static bool compare(DeleteDataEntry e1, DeleteDataEntry e2) { return e1.m_increase < e2.m_increase; } + + uint32_t m_index; + double m_increase; + }; // DeleteDataEntry + + // Needed to access protected members without having to cast from Node. + // It is more efficient than using member functions to access protected members. + friend class MVRTree; + friend class Leaf; + friend class Index; + friend class Tools::PointerPool<Node>; + }; // Node + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/PointerPoolNode.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/PointerPoolNode.h.svn-base new file mode 100644 index 000000000..33407df02 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/PointerPoolNode.h.svn-base @@ -0,0 +1,133 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Node.h" + +namespace Tools +{ + template<> class PointerPool<SpatialIndex::MVRTree::Node> + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + SpatialIndex::MVRTree::Node* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<SpatialIndex::MVRTree::Node> acquire() + { + if (! m_pool.empty()) + { + SpatialIndex::MVRTree::Node* p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + ++m_hits; + #endif + + return PoolPointer<SpatialIndex::MVRTree::Node>(p, this); + } + #ifndef NDEBUG + else + { + // fixme: well sort of... + ++m_pointerCount; + ++m_misses; + } + #endif + + return PoolPointer<SpatialIndex::MVRTree::Node>(); + } + + void release(SpatialIndex::MVRTree::Node* p) + { + if (p != 0) + { + if (m_pool.size() < m_capacity) + { + if (p->m_pData != 0) + { + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + if (p->m_pData[cChild] != 0) delete[] p->m_pData[cChild]; + } + } + + p->m_level = 0; + p->m_identifier = -1; + p->m_children = 0; + p->m_totalDataLength = 0; + + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + protected: + uint32_t m_capacity; + std::stack<SpatialIndex::MVRTree::Node*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Statistics.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Statistics.cc.svn-base new file mode 100644 index 000000000..3ffbcefae --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Statistics.cc.svn-base @@ -0,0 +1,191 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Statistics.h" + +using namespace SpatialIndex::MVRTree; + +Statistics::Statistics() +{ + reset(); +} + +Statistics::Statistics(const Statistics& s) +{ + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u32DeadIndexNodes = s.m_u32DeadIndexNodes; + m_u32DeadLeafNodes = s.m_u32DeadLeafNodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u64TotalData = s.m_u64TotalData; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; +} + +Statistics::~Statistics() +{ +} + +Statistics& Statistics::operator=(const Statistics& s) +{ + if (this != &s) + { + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u32DeadIndexNodes = s.m_u32DeadIndexNodes; + m_u32DeadLeafNodes = s.m_u32DeadLeafNodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u64TotalData = s.m_u64TotalData; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; + } + + return *this; +} + +uint64_t Statistics::getReads() const +{ + return m_u64Reads; +} + +uint64_t Statistics::getWrites() const +{ + return m_u64Writes; +} + +uint32_t Statistics::getNumberOfNodes() const +{ + return m_u32Nodes; +} + +uint64_t Statistics::getNumberOfData() const +{ + return m_u64Data; +} + +uint64_t Statistics::getSplits() const +{ + return m_u64Splits; +} + +uint64_t Statistics::getHits() const +{ + return m_u64Hits; +} + +uint64_t Statistics::getMisses() const +{ + return m_u64Misses; +} + +uint64_t Statistics::getAdjustments() const +{ + return m_u64Adjustments; +} + +uint64_t Statistics::getQueryResults() const +{ + return m_u64QueryResults; +} + +uint32_t Statistics::getTreeHeight() const +{ + uint32_t ret = 0; + + for (size_t cIndex = 0; cIndex < m_treeHeight.size(); ++cIndex) + { + ret = std::max(ret, m_treeHeight[cIndex]); + } + + return ret; +} + +uint32_t Statistics::getNumberOfNodesInLevel(uint32_t l) const +{ + try + { + return m_nodesInLevel.at(l); + } + catch (...) + { + throw Tools::IndexOutOfBoundsException(l); + } +} + +void Statistics::reset() +{ + m_u64Reads = 0; + m_u64Writes = 0; + m_u64Splits = 0; + m_u64Hits = 0; + m_u64Misses = 0; + m_u32Nodes = 0; + m_u32DeadIndexNodes = 0; + m_u32DeadLeafNodes = 0; + m_u64Adjustments = 0; + m_u64QueryResults = 0; + m_u64Data = 0; + m_u64TotalData = 0; + m_treeHeight.clear(); + m_nodesInLevel.clear(); +} + +std::ostream& SpatialIndex::MVRTree::operator<<(std::ostream& os, const Statistics& s) +{ + os << "Reads: " << s.m_u64Reads << std::endl + << "Writes: " << s.m_u64Writes << std::endl + << "Hits: " << s.m_u64Hits << std::endl + << "Misses: " << s.m_u64Misses << std::endl + << "Number of live data: " << s.m_u64Data << std::endl + << "Total number of data: " << s.m_u64TotalData << std::endl + << "Number of nodes: " << s.m_u32Nodes << std::endl + << "Numer of dead index nodes: " << s.m_u32DeadIndexNodes << std::endl + << "Numer of dead leaf nodes: " << s.m_u32DeadLeafNodes << std::endl; + + for (size_t cTree = 0; cTree < s.m_treeHeight.size(); ++cTree) + { + os << "Tree " << cTree << ", Height " << s.m_treeHeight[cTree] << std::endl; + } + + for (size_t cLevel = 0; cLevel < s.m_nodesInLevel.size(); ++cLevel) + { + os << "Level " << cLevel << " pages: " << s.m_nodesInLevel[cLevel] << std::endl; + } + + os << "Splits: " << s.m_u64Splits << std::endl + << "Adjustments: " << s.m_u64Adjustments << std::endl + << "Query results: " << s.m_u64QueryResults << std::endl; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Statistics.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Statistics.h.svn-base new file mode 100644 index 000000000..249a98cac --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/.svn/text-base/Statistics.h.svn-base @@ -0,0 +1,99 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class MVRTree; + class Node; + class Leaf; + class Index; + + class Statistics : public SpatialIndex::IStatistics + { + public: + Statistics(); + Statistics(const Statistics&); + virtual ~Statistics(); + Statistics& operator=(const Statistics&); + + // + // IStatistics interface + // + virtual uint64_t getReads() const; + virtual uint64_t getWrites() const; + virtual uint32_t getNumberOfNodes() const; + virtual uint64_t getNumberOfData() const; + + virtual uint64_t getSplits() const; + virtual uint64_t getHits() const; + virtual uint64_t getMisses() const; + virtual uint64_t getAdjustments() const; + virtual uint64_t getQueryResults() const; + virtual uint32_t getTreeHeight() const; + virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const; + + private: + void reset(); + + uint64_t m_u64Reads; + + uint64_t m_u64Writes; + + uint64_t m_u64Splits; + + uint64_t m_u64Hits; + + uint64_t m_u64Misses; + + uint32_t m_u32Nodes; + + uint32_t m_u32DeadIndexNodes; + + uint32_t m_u32DeadLeafNodes; + + uint64_t m_u64Adjustments; + + uint64_t m_u64QueryResults; + + uint64_t m_u64Data; + + uint64_t m_u64TotalData; + + std::vector<uint32_t> m_treeHeight; + + std::vector<uint32_t> m_nodesInLevel; + + friend class MVRTree; + friend class Node; + friend class Index; + friend class Leaf; + + friend std::ostream& operator<<(std::ostream& os, const Statistics& s); + }; // Statistics + + std::ostream& operator<<(std::ostream& os, const Statistics& s); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Index.cc b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Index.cc new file mode 100644 index 000000000..ba5d0e113 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Index.cc @@ -0,0 +1,429 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MVRTree.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" + +using namespace SpatialIndex::MVRTree; + +Index::~Index() +{ +} + +Index::Index(SpatialIndex::MVRTree::MVRTree* pTree, id_type id, uint32_t level) : Node(pTree, id, level, pTree->m_indexCapacity) +{ +} + +NodePtr Index::chooseSubtree(const TimeRegion& mbr, uint32_t insertionLevel, std::stack<id_type>& pathBuffer) +{ + if (m_level == insertionLevel) return NodePtr(this, &(m_pTree->m_indexPool)); + + pathBuffer.push(m_identifier); + + uint32_t child = 0; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + child = findLeastEnlargement(mbr); + break; + case RV_RSTAR: + if (m_level == 1) + { + // if this node points to leaves... + child = findLeastOverlap(mbr); + } + else + { + child = findLeastEnlargement(mbr); + } + break; + default: + throw Tools::NotSupportedException("Index::chooseSubtree: Tree variant not supported."); + } + assert (child != std::numeric_limits<uint32_t>::max()); + + NodePtr n = m_pTree->readNode(m_pIdentifier[child]); + NodePtr ret = n->chooseSubtree(mbr, insertionLevel, pathBuffer); + assert(n.unique()); + if (ret.get() == n.get()) n.relinquish(); + + return ret; +} + +NodePtr Index::findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // check live nodes only. + if (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max()) continue; + //if (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max() || + // m_ptrMBR[cChild]->m_startTime > mbr.m_startTime) continue; + + if (m_ptrMBR[cChild]->containsRegion(mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findLeaf(mbr, id, pathBuffer); + if (n.get() == l.get()) n.relinquish(); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} + +void Index::split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + default: + throw Tools::NotSupportedException("Index::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_indexPool.acquire(); + pRight = m_pTree->m_indexPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Index(m_pTree, m_identifier, m_level), &(m_pTree->m_indexPool)); + if (pRight.get() == 0) pRight = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(0, 0, *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(0, 0, *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + } +} + +uint32_t Index::findLeastEnlargement(const TimeRegion& r) const +{ + double area = std::numeric_limits<double>::max(); + uint32_t best = std::numeric_limits<uint32_t>::max(); + + TimeRegionPtr t = m_pTree->m_regionPool.acquire(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // if this child is already dead do not consider it. + if (m_ptrMBR[cChild]->m_endTime <= r.m_startTime) continue; + + m_ptrMBR[cChild]->getCombinedRegion(*t, r); + + double a = m_ptrMBR[cChild]->getArea(); + double enl = t->getArea() - a; + + if (enl < area) + { + area = enl; + best = cChild; + } + else if ( + enl > area - std::numeric_limits<double>::epsilon() && + enl < area + std::numeric_limits<double>::epsilon()) + { + if (a < m_ptrMBR[best]->getArea()) best = cChild; + } + } + +#ifndef NDEBUG + if (best == std::numeric_limits<uint32_t>::max()) + { + std::ostringstream s; + s << "findLeastEnlargement: All entries of node " << m_identifier << " are dead."; + throw Tools::IllegalStateException(s.str()); + } +#endif + + return best; +} + +uint32_t Index::findLeastOverlap(const TimeRegion& r) const +{ + OverlapEntry** entries = new OverlapEntry*[m_children]; + + double leastOverlap = std::numeric_limits<double>::max(); + double me = std::numeric_limits<double>::max(); + OverlapEntry* best = 0; + uint32_t cLiveEntries = 0; + + // find combined region and enlargement of every entry and store it. + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_ptrMBR[cChild]->m_endTime <= r.m_startTime) continue; + + try + { + entries[cLiveEntries] = new OverlapEntry(); + } + catch (...) + { + for (uint32_t i = 0; i < cLiveEntries; ++i) delete entries[i]; + delete[] entries; + throw; + } + + entries[cLiveEntries]->m_index = cChild; + entries[cLiveEntries]->m_original = m_ptrMBR[cChild]; + entries[cLiveEntries]->m_combined = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->getCombinedRegion(*(entries[cLiveEntries]->m_combined), r); + entries[cLiveEntries]->m_oa = entries[cLiveEntries]->m_original->getArea(); + entries[cLiveEntries]->m_ca = entries[cLiveEntries]->m_combined->getArea(); + entries[cLiveEntries]->m_enlargement = entries[cLiveEntries]->m_ca - entries[cLiveEntries]->m_oa; + + if (entries[cLiveEntries]->m_enlargement < me) + { + me = entries[cLiveEntries]->m_enlargement; + best = entries[cLiveEntries]; + } + else if (entries[cLiveEntries]->m_enlargement == me && entries[cLiveEntries]->m_oa < best->m_oa) + { + best = entries[cLiveEntries]; + } + ++cLiveEntries; + } + +#ifndef NDEBUG + if (cLiveEntries == 0) + { + std::ostringstream s; + s << "findLeastOverlap: All entries of node " << m_identifier << " are dead."; + throw Tools::IllegalStateException(s.str()); + } +#endif + + if (me < -std::numeric_limits<double>::epsilon() || me > std::numeric_limits<double>::epsilon()) + { + uint32_t cIterations; + + if (cLiveEntries > m_pTree->m_nearMinimumOverlapFactor) + { + // sort entries in increasing order of enlargement. + ::qsort(entries, cLiveEntries, + sizeof(OverlapEntry*), + OverlapEntry::compareEntries); + assert(entries[0]->m_enlargement <= entries[m_children - 1]->m_enlargement); + + cIterations = m_pTree->m_nearMinimumOverlapFactor; + } + else + { + cIterations = cLiveEntries; + } + + // calculate overlap of most important original entries (near minimum overlap cost). + for (uint32_t cIndex = 0; cIndex < cIterations; ++cIndex) + { + double dif = 0.0; + OverlapEntry* e = entries[cIndex]; + + for (uint32_t cChild = 0; cChild < cLiveEntries; ++cChild) + { + if (cIndex != cChild) + { + double f = e->m_combined->getIntersectingArea(*(entries[cChild]->m_original)); + if (f != 0.0) dif += f - e->m_original->getIntersectingArea(*(entries[cChild]->m_original)); + } + } // for (cChild) + + if (dif < leastOverlap) + { + leastOverlap = dif; + best = e; + } + else if (dif == leastOverlap) + { + if (e->m_enlargement == best->m_enlargement) + { + // keep the one with least area. + if (e->m_original->getArea() < best->m_original->getArea()) best = e; + } + else + { + // keep the one with least enlargement. + if (e->m_enlargement < best->m_enlargement) best = e; + } + } + } // for (cIndex) + } + + uint32_t ret = best->m_index; + + for (uint32_t cChild = 0; cChild < cLiveEntries; ++cChild) + { + delete entries[cChild]; + } + delete[] entries; + + return ret; +} + +void Index::adjustTree(Node* n, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n->m_identifier) break; + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + bool bContained = m_nodeMBR.containsRegion(n->m_nodeMBR); + bool bTouches = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool bRecompute = (! bContained || (bTouches && m_pTree->m_bTightMBRs)); + + // we should not adjust time here + double st = m_ptrMBR[child]->m_startTime; + double en = m_ptrMBR[child]->m_endTime; + *(m_ptrMBR[child]) = n->m_nodeMBR; + m_ptrMBR[child]->m_startTime = st; + m_ptrMBR[child]->m_endTime = en; + + if (bRecompute) + { + // no need to update times here. The inserted MBR is younger than all nodes. + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + m_pTree->writeNode(this); + + if (bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} + +void Index::adjustTree(Node* n, Node* nn, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child, child2 = m_capacity; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == nn->m_identifier) child2 = child; + if (m_pIdentifier[child] == n->m_identifier) break; + } + + if (child2 == m_capacity) + { + for (child2 = child + 1; child2 < m_children; ++child2) + { + if (m_pIdentifier[child2] == nn->m_identifier) break; + } + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + // 3. the SIBLING MBR is touching. + bool b1 = m_nodeMBR.containsRegion(n->m_nodeMBR); + bool b2 = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool b3 = m_nodeMBR.touchesRegion(*(m_ptrMBR[child2])); + bool bRecompute = (! b1) || ((b2 || b3) && m_pTree->m_bTightMBRs); + + // we should not adjust time here + double st = m_ptrMBR[child]->m_startTime; + double en = m_ptrMBR[child]->m_endTime; + *(m_ptrMBR[child]) = n->m_nodeMBR; + m_ptrMBR[child]->m_startTime = st; + m_ptrMBR[child]->m_endTime = en; + + st = m_ptrMBR[child2]->m_startTime; + en = m_ptrMBR[child2]->m_endTime; + *(m_ptrMBR[child2]) = nn->m_nodeMBR; + m_ptrMBR[child2]->m_startTime = st; + m_ptrMBR[child2]->m_endTime = en; + + if (bRecompute) + { + // no need to update times here. The inserted MBR is younger than all nodes. + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + m_pTree->writeNode(this); + + if (bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Index.h b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Index.h new file mode 100644 index 000000000..e5fa86a8c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Index.h @@ -0,0 +1,75 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class Index : public Node + { + public: + virtual ~Index(); + + private: + Index(MVRTree* pTree, id_type id, uint32_t level); + + virtual NodePtr chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& left, NodePtr& right, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + + uint32_t findLeastEnlargement(const TimeRegion&) const; + uint32_t findLeastOverlap(const TimeRegion&) const; + + void adjustTree(Node*, std::stack<id_type>&); + void adjustTree(Node* n, Node* nn, std::stack<id_type>& pathBuffer); + + class OverlapEntry + { + public: + uint32_t m_index; + double m_enlargement; + TimeRegionPtr m_original; + TimeRegionPtr m_combined; + double m_oa; + double m_ca; + + static int compareEntries(const void* pv1, const void* pv2) + { + OverlapEntry* pe1 = * (OverlapEntry**) pv1; + OverlapEntry* pe2 = * (OverlapEntry**) pv2; + + if (pe1->m_enlargement < pe2->m_enlargement) return -1; + if (pe1->m_enlargement > pe2->m_enlargement) return 1; + return 0; + } + }; // OverlapEntry + + friend class MVRTree; + friend class Node; + }; // Index + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Leaf.cc b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Leaf.cc new file mode 100644 index 000000000..925c170da --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Leaf.cc @@ -0,0 +1,103 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MVRTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::MVRTree; + +Leaf::~Leaf() +{ +} + +Leaf::Leaf(SpatialIndex::MVRTree::MVRTree* pTree, id_type id): Node(pTree, id, 0, pTree->m_leafCapacity) +{ +} + +NodePtr Leaf::chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) +{ + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + return NodePtr(this, &(m_pTree->m_leafPool)); +} + +NodePtr Leaf::findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + if (m_pIdentifier[cChild] == id && static_cast<Region>(mbr) == static_cast<Region>(*(m_ptrMBR[cChild]))) + return NodePtr(this, &(m_pTree->m_leafPool)); + } + + return NodePtr(); +} + +void Leaf::split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2, mbr2, id2, bInsertMbr2); + break; + default: + throw Tools::NotSupportedException("Leaf::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_leafPool.acquire(); + pRight = m_pTree->m_leafPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + if (pRight.get() == 0) pRight = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(m_pDataLength[g1[cIndex]], m_pData[g1[cIndex]], *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g1[cIndex]] = 0; + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(m_pDataLength[g2[cIndex]], m_pData[g2[cIndex]], *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g2[cIndex]] = 0; + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Leaf.h b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Leaf.h new file mode 100644 index 000000000..02d653c45 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Leaf.h @@ -0,0 +1,48 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class Leaf : public Node + { + public: + virtual ~Leaf(); + + private: + Leaf(MVRTree* pTree, id_type id); + + virtual NodePtr chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& left, NodePtr& right, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + + friend class MVRTree; + friend class Node; + }; // Leaf + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/MVRTree.cc b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/MVRTree.cc new file mode 100644 index 000000000..7520e6689 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/MVRTree.cc @@ -0,0 +1,1423 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" +#include "MVRTree.h" + +#include <cstring> + +using namespace SpatialIndex::MVRTree; + +SpatialIndex::MVRTree::Data::Data(uint32_t len, byte* pData, TimeRegion& r, id_type id) + : m_id(id), m_region(r), m_pData(0), m_dataLength(len) +{ + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, pData, m_dataLength); + } +} + +SpatialIndex::MVRTree::Data::~Data() +{ + delete[] m_pData; +} + +SpatialIndex::MVRTree::Data* SpatialIndex::MVRTree::Data::clone() +{ + return new Data(m_dataLength, m_pData, m_region, m_id); +} + +SpatialIndex::id_type SpatialIndex::MVRTree::Data::getIdentifier() const +{ + return m_id; +} + +void SpatialIndex::MVRTree::Data::getShape(IShape** out) const +{ + *out = new TimeRegion(m_region); +} + +void SpatialIndex::MVRTree::Data::getData(uint32_t& len, byte** data) const +{ + len = m_dataLength; + *data = 0; + + if (m_dataLength > 0) + { + *data = new byte[m_dataLength]; + memcpy(*data, m_pData, m_dataLength); + } +} + +uint32_t SpatialIndex::MVRTree::Data::getByteArraySize() +{ + return + sizeof(id_type) + + sizeof(uint32_t) + + m_dataLength + + m_region.getByteArraySize(); +} + +void SpatialIndex::MVRTree::Data::loadFromByteArray(const byte* ptr) +{ + memcpy(&m_id, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + delete[] m_pData; + m_pData = 0; + + memcpy(&m_dataLength, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, ptr, m_dataLength); + ptr += m_dataLength; + } + + m_region.loadFromByteArray(ptr); +} + +void SpatialIndex::MVRTree::Data::storeToByteArray(byte** data, uint32_t& len) +{ + // it is thread safe this way. + uint32_t regionsize; + byte* regiondata = 0; + m_region.storeToByteArray(®iondata, regionsize); + + len = sizeof(id_type) + sizeof(uint32_t) + m_dataLength + regionsize; + + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_id, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_dataLength, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + memcpy(ptr, m_pData, m_dataLength); + ptr += m_dataLength; + } + + memcpy(ptr, regiondata, regionsize); + delete[] regiondata; + // ptr += regionsize; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::MVRTree::returnMVRTree(SpatialIndex::IStorageManager& sm, Tools::PropertySet& ps) +{ + SpatialIndex::ISpatialIndex* si = new SpatialIndex::MVRTree::MVRTree(sm, ps); + return si; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::MVRTree::createNewMVRTree( + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + MVRTreeVariant rv, + id_type& indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = fillFactor; + ps.setProperty("FillFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = indexCapacity; + ps.setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = leafCapacity; + ps.setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = dimension; + ps.setProperty("Dimension", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = rv; + ps.setProperty("TreeVariant", var); + + ISpatialIndex* ret = returnMVRTree(sm, ps); + + var.m_varType = Tools::VT_LONGLONG; + var = ps.getProperty("IndexIdentifier"); + indexIdentifier = var.m_val.llVal; + + return ret; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::MVRTree::loadMVRTree(IStorageManager& sm, id_type indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = indexIdentifier; + ps.setProperty("IndexIdentifier", var); + + return returnMVRTree(sm, ps); +} + +SpatialIndex::MVRTree::MVRTree::MVRTree(IStorageManager& sm, Tools::PropertySet& ps) : + m_pStorageManager(&sm), + m_headerID(StorageManager::NewPage), + m_treeVariant(RV_RSTAR), + m_fillFactor(0.7), + m_indexCapacity(100), + m_leafCapacity(100), + m_nearMinimumOverlapFactor(32), + m_splitDistributionFactor(0.4), + m_reinsertFactor(0.3), + m_strongVersionOverflow(0.8), + //m_strongVersionUnderflow(0.2), + m_versionUnderflow(0.3), + m_dimension(2), + m_bTightMBRs(true), + m_bHasVersionCopied(false), + m_currentTime(0.0), + m_pointPool(500), + m_regionPool(1000), + m_indexPool(100), + m_leafPool(100) +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + + Tools::Variant var = ps.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType == Tools::VT_LONGLONG) m_headerID = var.m_val.llVal; + else if (var.m_varType == Tools::VT_LONG) m_headerID = var.m_val.lVal; + // for backward compatibility only. + else throw Tools::IllegalArgumentException("MVRTree: Property IndexIdentifier must be Tools::VT_LONGLONG"); + + initOld(ps); + } + else + { + initNew(ps); + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = m_headerID; + ps.setProperty("IndexIdentifier", var); + } +} + +SpatialIndex::MVRTree::MVRTree::~MVRTree() +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_destroy(&m_rwLock); +#endif + + storeHeader(); +} + +// +// ISpatialIndex interface +// + +void SpatialIndex::MVRTree::MVRTree::insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&shape); + if (ti == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IInterval interface."); + if (ti->getLowerBound() < m_currentTime) throw Tools::IllegalArgumentException("insertData: Shape start time is older than tree current time."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("insertData: cannot acquire an exclusive lock"); +#endif + + try + { + // convert the shape into a TimeRegion (R-Trees index regions only; i.e., approximations of the shapes). + Region mbrold; + shape.getMBR(mbrold); + + TimeRegionPtr mbr = m_regionPool.acquire(); + mbr->makeDimension(mbrold.m_dimension); + + memcpy(mbr->m_pLow, mbrold.m_pLow, mbrold.m_dimension * sizeof(double)); + memcpy(mbr->m_pHigh, mbrold.m_pHigh, mbrold.m_dimension * sizeof(double)); + mbr->m_startTime = ti->getLowerBound(); + mbr->m_endTime = std::numeric_limits<double>::max(); + + byte* buffer = 0; + + if (len > 0) + { + buffer = new byte[len]; + memcpy(buffer, pData, len); + } + + insertData_impl(len, buffer, *mbr, id); + // the buffer is stored in the tree. Do not delete here. + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +bool SpatialIndex::MVRTree::MVRTree::deleteData(const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("deleteData: Shape has the wrong number of dimensions."); + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&shape); + if (ti == 0) throw Tools::IllegalArgumentException("deleteData: Shape does not support the Tools::IInterval interface."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("deleteData: cannot acquire an exclusive lock"); +#endif + + try + { + Region mbrold; + shape.getMBR(mbrold); + + TimeRegionPtr mbr = m_regionPool.acquire(); + mbr->makeDimension(mbrold.m_dimension); + + memcpy(mbr->m_pLow, mbrold.m_pLow, mbrold.m_dimension * sizeof(double)); + memcpy(mbr->m_pHigh, mbrold.m_pHigh, mbrold.m_dimension * sizeof(double)); + mbr->m_startTime = ti->getLowerBound(); + mbr->m_endTime = ti->getUpperBound(); + + bool ret = deleteData_impl(*mbr, id); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + return ret; + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::containsWhatQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("containsWhatQuery: Shape has the wrong number of dimensions."); + rangeQuery(ContainmentQuery, query, v); +} + +void SpatialIndex::MVRTree::MVRTree::intersectsWithQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("intersectsWithQuery: Shape has the wrong number of dimensions."); + rangeQuery(IntersectionQuery, query, v); +} + +void SpatialIndex::MVRTree::MVRTree::pointLocationQuery(const Point& query, IVisitor& v) +{ + if (query.m_dimension != m_dimension) throw Tools::IllegalArgumentException("pointLocationQuery: Shape has the wrong number of dimensions."); + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&query); + if (ti == 0) throw Tools::IllegalArgumentException("pointLocationQuery: Shape does not support the Tools::IInterval interface."); + TimeRegion r(query, query, *ti); + rangeQuery(IntersectionQuery, r, v); +} + +void SpatialIndex::MVRTree::MVRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) +{ + throw Tools::IllegalStateException("nearestNeighborQuery: not impelmented yet."); +} + +void SpatialIndex::MVRTree::MVRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + NNComparator nnc; + nearestNeighborQuery(k, query, v, nnc); +} + +void SpatialIndex::MVRTree::MVRTree::selfJoinQuery(const IShape& query, IVisitor& v) +{ + throw Tools::IllegalStateException("selfJoinQuery: not impelmented yet."); +} + +void SpatialIndex::MVRTree::MVRTree::queryStrategy(IQueryStrategy& qs) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("queryStrategy: cannot acquire a shared lock"); +#endif + + id_type next = m_roots[m_roots.size() - 1].m_id; + bool hasNext = true; + + try + { + while (hasNext) + { + NodePtr n = readNode(next); + qs.getNextEntry(*n, next, hasNext); + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::getIndexProperties(Tools::PropertySet& out) const +{ + Tools::Variant var; + + // dimension + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_dimension; + out.setProperty("Dimension", var); + + // index capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexCapacity; + out.setProperty("IndexCapacity", var); + + // leaf capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafCapacity; + out.setProperty("LeafCapacity", var); + + // Tree variant + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = m_treeVariant; + out.setProperty("TreeVariant", var); + + // fill factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_fillFactor; + out.setProperty("FillFactor", var); + + // near minimum overlap factor + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_nearMinimumOverlapFactor; + out.setProperty("NearMinimumOverlapFactor", var); + + // split distribution factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_splitDistributionFactor; + out.setProperty("SplitDistributionFactor", var); + + // reinsert factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_reinsertFactor; + out.setProperty("ReinsertFactor", var); + + // tight MBRs + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = m_bTightMBRs; + out.setProperty("EnsureTightMBRs", var); + + // index pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexPool.getCapacity(); + out.setProperty("IndexPoolCapacity", var); + + // leaf pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafPool.getCapacity(); + out.setProperty("LeafPoolCapacity", var); + + // region pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_regionPool.getCapacity(); + out.setProperty("RegionPoolCapacity", var); + + // point pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_pointPool.getCapacity(); + out.setProperty("PointPoolCapacity", var); + + // strong version overflow + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_strongVersionOverflow; + out.setProperty("StrongVersionOverflow", var); + + // strong version underflow + //var.m_varType = Tools::VT_DOUBLE; + //var.m_val.dblVal = m_strongVersionUnderflow; + //out.setProperty("StrongVersionUnderflow", var); + + // weak version underflow + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_versionUnderflow; + out.setProperty("VersionUnderflow", var); +} + +void SpatialIndex::MVRTree::MVRTree::addCommand(ICommand* pCommand, CommandType ct) +{ + switch (ct) + { + case CT_NODEREAD: + m_readNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEWRITE: + m_writeNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEDELETE: + m_deleteNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + } +} + +bool SpatialIndex::MVRTree::MVRTree::isIndexValid() +{ + bool ret = true; + std::stack<ValidateEntry> st; + std::set<id_type> visitedEntries; + uint32_t degenerateEntries = 0; + + for (uint32_t cRoot = 0; cRoot < m_roots.size(); ++cRoot) + { + NodePtr root = readNode(m_roots[cRoot].m_id); + + if (root->m_level != m_stats.m_treeHeight[cRoot] - 1) + { + std::cerr << "Invalid tree height." << std::endl; + return false; + } + + ValidateEntry e(0, root->m_nodeMBR, root); + e.m_bIsDead = (root->m_nodeMBR.m_endTime < std::numeric_limits<double>::max()) ? true : false; + st.push(e); + } + + while (! st.empty()) + { + ValidateEntry e = st.top(); st.pop(); + + std::set<id_type>::iterator itSet = visitedEntries.find(e.m_pNode->m_identifier); + if (itSet == visitedEntries.end()) + { + visitedEntries.insert(e.m_pNode->m_identifier); + if (e.m_pNode->m_nodeMBR.m_startTime == e.m_pNode->m_nodeMBR.m_endTime) ++degenerateEntries; + } + + TimeRegion tmpRegion; + tmpRegion = m_infiniteRegion; + + for (uint32_t cDim = 0; cDim < tmpRegion.m_dimension; ++cDim) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + tmpRegion.m_pLow[cDim] = std::min(tmpRegion.m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pLow[cDim]); + tmpRegion.m_pHigh[cDim] = std::max(tmpRegion.m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + + tmpRegion.m_startTime = e.m_pNode->m_nodeMBR.m_startTime; + tmpRegion.m_endTime = e.m_pNode->m_nodeMBR.m_endTime; + if (! (tmpRegion == e.m_pNode->m_nodeMBR)) + { + std::cerr << "Invalid parent information." << std::endl; + ret = false; + } + + if (! e.m_bIsDead) + { + tmpRegion.m_startTime = e.m_parentMBR.m_startTime; + tmpRegion.m_endTime = e.m_parentMBR.m_endTime; + if (! (tmpRegion == e.m_parentMBR)) + { + std::cerr << "Error in parent (Node id: " << e.m_pNode->m_identifier << ", Parent id: " << e.m_parentID << ")." << std::endl; + ret = false; + } + } + + if (e.m_pNode->m_level != 0) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]); + + bool bIsDead = + (e.m_pNode->m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max() || e.m_bIsDead) ? true : false; + + // if the parent says that this child is dead, force it dead since + // this information is not propagated for efficiency and is inconsistent. + if (bIsDead) ptrN->m_nodeMBR.m_endTime = e.m_pNode->m_ptrMBR[cChild]->m_endTime; + + ValidateEntry tmpEntry(e.m_pNode->m_identifier, *(e.m_pNode->m_ptrMBR[cChild]), ptrN); + tmpEntry.m_bIsDead = bIsDead; + st.push(tmpEntry); + } + } + } + + //std::cerr << "Total accessible nodes: " << visitedEntries.size() << std::endl; + //std::cerr << "Degenerate nodes: " << degenerateEntries << std::endl; + + return ret; +} + +void SpatialIndex::MVRTree::MVRTree::getStatistics(IStatistics** out) const +{ + *out = new Statistics(m_stats); +} + +void SpatialIndex::MVRTree::MVRTree::initNew(Tools::PropertySet& ps) +{ + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG || (var.m_val.lVal != RV_LINEAR && var.m_val.lVal != RV_QUADRATIC && var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initNew: Property TreeVariant must be Tools::VT_LONG and of MVRTreeVariant type"); + + m_treeVariant = static_cast<MVRTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + //((m_treeVariant == RV_LINEAR || m_treeVariant == RV_QUADRATIC) && var.m_val.dblVal > 0.5) || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property FillFactor must be Tools::VT_DOUBLE and in (0.0, 1.0) for RSTAR, (0.0, 0.5) for LINEAR and QUADRATIC"); + + m_fillFactor = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 10) + throw Tools::IllegalArgumentException("initNew: Property IndexCapacity must be Tools::VT_ULONG and >= 10"); + + m_indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 10) + throw Tools::IllegalArgumentException("initNew: Property LeafCapacity must be Tools::VT_ULONG and >= 10"); + + m_leafCapacity = var.m_val.ulVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 1 || var.m_val.ulVal > m_indexCapacity || var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) throw Tools::IllegalArgumentException("initNew: Property Dimension must be greater than 1"); + + m_dimension = var.m_val.ulVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initNew: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initNew: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + // strong version overflow + var = ps.getProperty("StrongVersionOverflow"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property StrongVersionOverflow must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_strongVersionOverflow = var.m_val.dblVal; + } + + // strong version underflow + //var = ps.getProperty("StrongVersionUnderflow"); + //if (var.m_varType != Tools::VT_EMPTY) + //{ + // if (var.m_varType != Tools::VT_DOUBLE || + // var.m_val.dblVal <= 0.0 || + // var.m_val.dblVal >= 1.0) throw Tools::IllegalArgumentException("Property StrongVersionUnderflow must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + // m_strongVersionUnderflow = var.m_val.dblVal; + //} + + // weak version underflow + var = ps.getProperty("VersionUnderflow"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property VersionUnderflow must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_versionUnderflow = var.m_val.dblVal; + } + + m_infiniteRegion.makeInfinite(m_dimension); + + m_stats.m_treeHeight.push_back(1); + m_stats.m_nodesInLevel.push_back(1); + + Leaf root(this, -1); + root.m_nodeMBR.m_startTime = 0.0; + root.m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + writeNode(&root); + m_roots.push_back(RootEntry(root.m_identifier, root.m_nodeMBR.m_startTime, root.m_nodeMBR.m_endTime)); + + storeHeader(); +} + +void SpatialIndex::MVRTree::MVRTree::initOld(Tools::PropertySet& ps) +{ + loadHeader(); + + // only some of the properties may be changed. + // the rest are just ignored. + + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_LONG || (var.m_val.lVal != RV_LINEAR && var.m_val.lVal != RV_QUADRATIC && var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initOld: Property TreeVariant must be Tools::VT_LONG and of MVRTreeVariant type"); + + m_treeVariant = static_cast<MVRTreeVariant>(var.m_val.lVal); + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 1 || var.m_val.ulVal > m_indexCapacity || var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE ||var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initOld: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); +} + +void SpatialIndex::MVRTree::MVRTree::storeHeader() +{ + const uint32_t headerSize = + sizeof(uint32_t) + // size of m_roots + static_cast<uint32_t>(m_roots.size()) + * (sizeof(id_type) + 2 * sizeof(double)) + // m_roots + sizeof(MVRTreeVariant) + // m_treeVariant + sizeof(double)+ // m_fillFactor + sizeof(uint32_t) + // m_indexCapacity + sizeof(uint32_t) + // m_leafCapacity + sizeof(uint32_t) + // m_nearMinimumOverlapFactor + sizeof(double) + // m_splitDistributionFactor + sizeof(double) + // m_reinsertFactor + sizeof(uint32_t) + // m_dimension + sizeof(byte) + // m_bTightMBRs + sizeof(uint32_t) + // m_stats.m_nodes + sizeof(uint64_t) + // m_stats.m_totalData + sizeof(uint32_t) + // m_stats.m_deadIndexNodes + sizeof(uint32_t) + // m_stats.m_deadLeafNodes + sizeof(uint64_t) + // m_stats.m_data + sizeof(uint32_t) + // size of m_stats.m_treeHeight + static_cast<uint32_t>(m_stats.m_treeHeight.size()) + * sizeof(uint32_t) + // m_stats.m_treeHeight + sizeof(double) + // m_strongVersionOverflow + //sizeof(double) + // m_strongVersionUnderflow + sizeof(double) + // m_versionUnderflow + sizeof(double) + // m_currentTime + sizeof(uint32_t) + // m_nodesInLevel size + static_cast<uint32_t>(m_stats.m_nodesInLevel.size()) + * sizeof(uint32_t); // m_nodesInLevel values + + byte* header = new byte[headerSize]; + byte* ptr = header; + + uint32_t u32I = static_cast<uint32_t>(m_roots.size()); + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (size_t cIndex = 0; cIndex < m_roots.size(); ++cIndex) + { + RootEntry& e = m_roots[cIndex]; + memcpy(ptr, &(e.m_id), sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &(e.m_startTime), sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(e.m_endTime), sizeof(double)); + ptr += sizeof(double); + } + + memcpy(ptr, &m_treeVariant, sizeof(MVRTreeVariant)); + ptr += sizeof(MVRTreeVariant); + memcpy(ptr, &m_fillFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_indexCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_leafCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_nearMinimumOverlapFactor, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_splitDistributionFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_reinsertFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + byte c = (byte) m_bTightMBRs; + memcpy(ptr, &c, sizeof(byte)); + ptr += sizeof(byte); + memcpy(ptr, &(m_stats.m_u32Nodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u64TotalData), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(ptr, &(m_stats.m_u32DeadIndexNodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u32DeadLeafNodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u64Data), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + + u32I = static_cast<uint32_t>(m_stats.m_treeHeight.size()); + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (size_t cIndex = 0; cIndex < m_stats.m_treeHeight.size(); ++cIndex) + { + u32I = m_stats.m_treeHeight[cIndex]; + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + memcpy(ptr, &m_strongVersionOverflow, sizeof(double)); + ptr += sizeof(double); + //memcpy(ptr, &m_strongVersionUnderflow, sizeof(double)); + //ptr += sizeof(double); + memcpy(ptr, &m_versionUnderflow, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_currentTime, sizeof(double)); + ptr += sizeof(double); + + u32I = static_cast<uint32_t>(m_stats.m_nodesInLevel.size()); + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (size_t cLevel = 0; cLevel < m_stats.m_nodesInLevel.size(); ++cLevel) + { + u32I = m_stats.m_nodesInLevel[cLevel]; + memcpy(ptr, &u32I, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + m_pStorageManager->storeByteArray(m_headerID, headerSize, header); + + delete[] header; +} + +void SpatialIndex::MVRTree::MVRTree::loadHeader() +{ + uint32_t headerSize; + byte* header = 0; + m_pStorageManager->loadByteArray(m_headerID, headerSize, &header); + + byte* ptr = header; + + uint32_t rootsSize; + memcpy(&rootsSize, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cIndex = 0; cIndex < rootsSize; ++cIndex) + { + RootEntry e; + memcpy(&(e.m_id), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&(e.m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(e.m_endTime), ptr, sizeof(double)); + ptr += sizeof(double); + m_roots.push_back(e); + } + + memcpy(&m_treeVariant, ptr, sizeof(MVRTreeVariant)); + ptr += sizeof(MVRTreeVariant); + memcpy(&m_fillFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_indexCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_leafCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_nearMinimumOverlapFactor, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_splitDistributionFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_reinsertFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + byte c; + memcpy(&c, ptr, sizeof(byte)); + m_bTightMBRs = (c != 0); + ptr += sizeof(byte); + memcpy(&(m_stats.m_u32Nodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u64TotalData), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(&(m_stats.m_u32DeadIndexNodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u32DeadLeafNodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u64Data), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + + uint32_t treeHeightSize; + memcpy(&treeHeightSize, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cIndex = 0; cIndex < treeHeightSize; ++cIndex) + { + uint32_t u32I; + memcpy(&u32I, ptr, sizeof(uint32_t)); + m_stats.m_treeHeight.push_back(u32I); + ptr += sizeof(uint32_t); + } + + memcpy(&m_strongVersionOverflow, ptr, sizeof(double)); + ptr += sizeof(double); + //memcpy(&m_strongVersionUnderflow, ptr, sizeof(double)); + //ptr += sizeof(double); + memcpy(&m_versionUnderflow, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_currentTime, ptr, sizeof(double)); + ptr += sizeof(double); + + uint32_t nodesInLevelSize; + memcpy(&nodesInLevelSize, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < nodesInLevelSize; ++cLevel) + { + uint32_t u32I; + memcpy(&u32I, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + m_stats.m_nodesInLevel.push_back(u32I); + } + + delete[] header; +} + +void SpatialIndex::MVRTree::MVRTree::insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id) +{ + assert(mbr.getDimension() == m_dimension); + assert(m_currentTime <= mbr.m_startTime); + + std::stack<id_type> pathBuffer; + m_currentTime = mbr.m_startTime; + + NodePtr root = readNode(m_roots[m_roots.size() - 1].m_id); + NodePtr l = root->chooseSubtree(mbr, 0, pathBuffer); + + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mbr, id, pathBuffer, m_infiniteRegion, -1, false); + + ++(m_stats.m_u64Data); + ++(m_stats.m_u64TotalData); +} + +void SpatialIndex::MVRTree::MVRTree::insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, uint32_t level) +{ + assert(mbr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + + NodePtr root = readNode(m_roots[m_roots.size() - 1].m_id); + NodePtr l = root->chooseSubtree(mbr, level, pathBuffer); + + assert(l->m_level == level); + + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mbr, id, pathBuffer, m_infiniteRegion, -1, false); +} + +bool SpatialIndex::MVRTree::MVRTree::deleteData_impl(const TimeRegion& mbr, id_type id) +{ + assert(mbr.m_dimension == m_dimension); + + m_currentTime = mbr.m_endTime; + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_roots[m_roots.size() - 1].m_id); + NodePtr l = root->findLeaf(mbr, id, pathBuffer); + + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + + if (l.get() != 0) + { + l->deleteData(id, mbr.m_endTime, pathBuffer); + --(m_stats.m_u64Data); + return true; + } + + return false; +} + +SpatialIndex::id_type SpatialIndex::MVRTree::MVRTree::writeNode(Node* n) +{ + byte* buffer; + uint32_t dataLength; + n->storeToByteArray(&buffer, dataLength); + + id_type page; + if (n->m_identifier < 0) page = StorageManager::NewPage; + else page = n->m_identifier; + + try + { + m_pStorageManager->storeByteArray(page, dataLength, buffer); + delete[] buffer; + } + catch (InvalidPageException& e) + { + delete[] buffer; + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("writeNode: failed with Tools::InvalidPageException"); + } + + if (n->m_identifier < 0) + { + n->m_identifier = page; + ++(m_stats.m_u32Nodes); + } + + ++(m_stats.m_u64Writes); + + for (size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex) + { + m_writeNodeCommands[cIndex]->execute(*n); + } + + return page; +} + +SpatialIndex::MVRTree::NodePtr SpatialIndex::MVRTree::MVRTree::readNode(id_type id) +{ + uint32_t dataLength; + byte* buffer; + + try + { + m_pStorageManager->loadByteArray(id, dataLength, &buffer); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("readNode: failed with Tools::InvalidPageException"); + } + + try + { + uint32_t nodeType; + memcpy(&nodeType, buffer, sizeof(uint32_t)); + + NodePtr n; + + if (nodeType == PersistentIndex) n = m_indexPool.acquire(); + else if (nodeType == PersistentLeaf) n = m_leafPool.acquire(); + else throw Tools::IllegalStateException("readNode: failed reading the correct node type information"); + + if (n.get() == 0) + { + if (nodeType == PersistentIndex) n = NodePtr(new Index(this, -1, 0), &m_indexPool); + else if (nodeType == PersistentLeaf) n = NodePtr(new Leaf(this, -1), &m_leafPool); + } + + //n->m_pTree = this; + n->m_identifier = id; + n->loadFromByteArray(buffer); + + ++(m_stats.m_u64Reads); + + for (size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex) + { + m_readNodeCommands[cIndex]->execute(*n); + } + + delete[] buffer; + return n; + } + catch (...) + { + delete[] buffer; + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::deleteNode(Node* n) +{ + try + { + m_pStorageManager->deleteByteArray(n->m_identifier); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("deleteNode: failed with Tools::InvalidPageException"); + } + + --(m_stats.m_u32Nodes); + + for (size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex) + { + m_deleteNodeCommands[cIndex]->execute(*n); + } +} + +void SpatialIndex::MVRTree::MVRTree::rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v) +{ + // any shape that implements IInterval and IShape, can be used here. + // FIXME: I am not using ITimeShape yet, even though I should. + + const Tools::IInterval* ti = dynamic_cast<const Tools::IInterval*>(&query); + if (ti == 0) throw Tools::IllegalArgumentException("rangeQuery: Shape does not support the Tools::IInterval interface."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("rangeQuery: cannot acquire a shared lock"); +#endif + + try + { + std::set<id_type> visitedNodes; + std::set<id_type> visitedData; + std::stack<NodePtr> st; + std::vector<id_type> ids; + findRootIdentifiers(*ti, ids); + + for (size_t cRoot = 0; cRoot < ids.size(); ++cRoot) + { + NodePtr root = readNode(ids[cRoot]); + if (root->m_children > 0 && query.intersectsShape(root->m_nodeMBR)) st.push(root); + } + + while (! st.empty()) + { + NodePtr n = st.top(); st.pop(); + visitedNodes.insert(n->m_identifier); + + if (n->m_level == 0) + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (visitedData.find(n->m_pIdentifier[cChild]) != visitedData.end()) continue; + + bool b; + if (type == ContainmentQuery) b = (n->m_ptrMBR[cChild])->intersectsInterval(*ti) && query.containsShape(*(n->m_ptrMBR[cChild])); + else b = (n->m_ptrMBR[cChild])->intersectsInterval(*ti) && query.intersectsShape(*(n->m_ptrMBR[cChild])); + + if (b) + { + visitedData.insert(n->m_pIdentifier[cChild]); + Data data = Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + v.visitData(data); + ++(m_stats.m_u64QueryResults); + } + } + } + else + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if ( + visitedNodes.find(n->m_pIdentifier[cChild]) == visitedNodes.end() && + n->m_ptrMBR[cChild]->intersectsInterval(*ti) && + query.intersectsShape(*(n->m_ptrMBR[cChild]))) + st.push(readNode(n->m_pIdentifier[cChild])); + } + } + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::MVRTree::MVRTree::findRootIdentifiers(const Tools::IInterval& ti, std::vector<id_type>& ids) +{ + ids.clear(); + + for (size_t cRoot = 0; cRoot < m_roots.size(); ++cRoot) + { + RootEntry& e = m_roots[cRoot]; + if (ti.intersectsInterval(Tools::IT_RIGHTOPEN, e.m_startTime, e.m_endTime)) ids.push_back(e.m_id); + } +} + +std::string SpatialIndex::MVRTree::MVRTree::printRootInfo() const +{ + std::ostringstream s; + + for (size_t cRoot = 0; cRoot < m_roots.size(); ++cRoot) + { + const RootEntry& e = m_roots[cRoot]; + + s << "Root " << cRoot << ": Start " << e.m_startTime << ", End " << e.m_endTime << std::endl; + } + + return s.str(); +} + +std::ostream& SpatialIndex::MVRTree::operator<<(std::ostream& os, const MVRTree& t) +{ + os << "Dimension: " << t.m_dimension << std::endl + << "Fill factor: " << t.m_fillFactor << std::endl + << "Index capacity: " << t.m_indexCapacity << std::endl + << "Leaf capacity: " << t.m_leafCapacity << std::endl + << "Tight MBRs: " << ((t.m_bTightMBRs) ? "enabled" : "disabled") << std::endl; + + if (t.m_treeVariant == RV_RSTAR) + { + os << "Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl + << "Reinsert factor: " << t.m_reinsertFactor << std::endl + << "Split distribution factor: " << t.m_splitDistributionFactor << std::endl + << "Strong version overflow: " << t.m_strongVersionOverflow << std::endl + //<< "Strong version underflow: " << t.m_strongVersionUnderflow << std::endl + << "Weak version underflow: " << t.m_versionUnderflow << std::endl; + } + + // it is difficult to count utilization + //os << "Utilization: " << 100 * t.m_stats.m_totalData / (t.m_stats.getNumberOfNodesInLevel(0) * t.m_leafCapacity) << "%" << std::endl + + os << t.m_stats; + os << t.printRootInfo(); + + #ifndef NDEBUG + os << "Leaf pool hits: " << t.m_leafPool.m_hits << std::endl + << "Leaf pool misses: " << t.m_leafPool.m_misses << std::endl + << "Index pool hits: " << t.m_indexPool.m_hits << std::endl + << "Index pool misses: " << t.m_indexPool.m_misses << std::endl + << "Region pool hits: " << t.m_regionPool.m_hits << std::endl + << "Region pool misses: " << t.m_regionPool.m_misses << std::endl + << "Point pool hits: " << t.m_pointPool.m_hits << std::endl + << "Point pool misses: " << t.m_pointPool.m_misses << std::endl; + #endif + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/MVRTree.h b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/MVRTree.h new file mode 100644 index 000000000..cfbe33c1e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/MVRTree.h @@ -0,0 +1,222 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Statistics.h" +#include "Node.h" +#include "PointerPoolNode.h" + +namespace SpatialIndex +{ + namespace MVRTree + { + class MVRTree : public ISpatialIndex + { + class NNEntry; + class RootEntry; + + public: + MVRTree(IStorageManager&, Tools::PropertySet&); + // String Value Description + // ---------------------------------------------- + // IndexIndentifier VT_LONG If specified an existing index will be openened from the supplied + // storage manager with the given index id. Behaviour is unspecified + // if the index id or the storage manager are incorrect. + // Dimension VT_ULONG Dimensionality of the data that will be inserted. + // IndexCapacity VT_ULONG The index node capacity. Default is 100. + // LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. + // FillFactor VT_DOUBLE The fill factor. Default is 70% + // TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar + // NearMinimumOverlapFactor VT_ULONG Default is 32. + // SplitDistributionFactor VT_DOUBLE Default is 0.4 + // ReinsertFactor VT_DOUBLE Default is 0.3 + // EnsureTightMBRs VT_BOOL Default is true + // IndexPoolCapacity VT_LONG Default is 100 + // LeafPoolCapacity VT_LONG Default is 100 + // RegionPoolCapacity VT_LONG Default is 1000 + // PointPoolCapacity VT_LONG Default is 500 + // StrongVersionOverflow VT_DOUBLE Default is 0.8 + // VersionUnderflow VT_DOUBLE Default is 0.3 + + virtual ~MVRTree(); + + // + // ISpatialIndex interface + // + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id); + virtual bool deleteData(const IShape& shape, id_type id); + virtual void containsWhatQuery(const IShape& query, IVisitor& v); + virtual void intersectsWithQuery(const IShape& query, IVisitor& v); + virtual void pointLocationQuery(const Point& query, IVisitor& v); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator&); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v); + virtual void selfJoinQuery(const IShape& s, IVisitor& v); + virtual void queryStrategy(IQueryStrategy& qs); + virtual void getIndexProperties(Tools::PropertySet& out) const; + virtual void addCommand(ICommand* pCommand, CommandType ct); + virtual bool isIndexValid(); + virtual void getStatistics(IStatistics** out) const; + + private: + void initNew(Tools::PropertySet&); + void initOld(Tools::PropertySet& ps); + void storeHeader(); + void loadHeader(); + + void insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id); + void insertData_impl(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, uint32_t level); + bool deleteData_impl(const TimeRegion& mbr, id_type id); + + id_type writeNode(Node*); + NodePtr readNode(id_type id); + void deleteNode(Node* n); + + void rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v); + + void findRootIdentifiers(const Tools::IInterval& ti, std::vector<id_type>& ids); + std::string printRootInfo() const; + + IStorageManager* m_pStorageManager; + + std::vector<RootEntry> m_roots; + id_type m_headerID; + + MVRTreeVariant m_treeVariant; + + double m_fillFactor; + + uint32_t m_indexCapacity; + + uint32_t m_leafCapacity; + + uint32_t m_nearMinimumOverlapFactor; + // The R*-Tree 'p' constant, for calculating nearly minimum overlap cost. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles, Section 4.1] + + double m_splitDistributionFactor; + // The R*-Tree 'm' constant, for calculating spliting distributions. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles, Section 4.2] + + double m_reinsertFactor; + // The R*-Tree 'p' constant, for removing entries at reinserts. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles, Section 4.3] + + double m_strongVersionOverflow; + //double m_strongVersionUnderflow; + double m_versionUnderflow; + + uint32_t m_dimension; + + TimeRegion m_infiniteRegion; + + SpatialIndex::MVRTree::Statistics m_stats; + + bool m_bTightMBRs; + + bool m_bHasVersionCopied; + + double m_currentTime; + + Tools::PointerPool<Point> m_pointPool; + Tools::PointerPool<TimeRegion> m_regionPool; + Tools::PointerPool<Node> m_indexPool; + Tools::PointerPool<Node> m_leafPool; + + std::vector<Tools::SmartPointer<ICommand> > m_writeNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_readNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_deleteNodeCommands; + +#ifdef HAVE_PTHREAD_H + pthread_rwlock_t m_rwLock; +#else + bool m_rwLock; +#endif + + class RootEntry + { + public: + RootEntry() {} + RootEntry(id_type id, double s, double e) : m_id(id), m_startTime(s), m_endTime(e) {} + + id_type m_id; + double m_startTime; + double m_endTime; + }; // RootEntry + + class NNEntry + { + public: + id_type m_id; + IEntry* m_pEntry; + double m_minDist; + + NNEntry(id_type id, IEntry* e, double f) : m_id(id), m_pEntry(e), m_minDist(f) {} + ~NNEntry() {} + + struct greater : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_minDist > __y->m_minDist; } + }; + }; // NNEntry + + class NNComparator : public INearestNeighborComparator + { + public: + double getMinimumDistance(const IShape& query, const IShape& entry) + { + return query.getMinimumDistance(entry); + } + double getMinimumDistance(const IShape& query, const IData& data) + { + IShape* pR; + data.getShape(&pR); + double ret = query.getMinimumDistance(*pR); + delete pR; + return ret; + } + }; // NNComparator + + class ValidateEntry + { + public: + ValidateEntry(id_type pid, TimeRegion& r, NodePtr& pNode) : m_parentID(pid), m_parentMBR(r), m_pNode(pNode), m_bIsDead(false) {} + + id_type m_parentID; + TimeRegion m_parentMBR; + NodePtr m_pNode; + bool m_bIsDead; + }; // ValidateEntry + + friend class Node; + friend class Leaf; + friend class Index; + + friend std::ostream& operator<<(std::ostream& os, const MVRTree& t); + }; // MVRTree + + std::ostream& operator<<(std::ostream& os, const MVRTree& t); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Makefile.am new file mode 100644 index 000000000..8c28ebe12 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Makefile.am @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libmvrtree.la +INCLUDES = -I../../include +libmvrtree_la_SOURCES = Index.cc Leaf.cc Node.cc MVRTree.cc Statistics.cc Index.h Leaf.h MVRTree.h Node.h PointerPoolNode.h Statistics.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Node.cc b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Node.cc new file mode 100644 index 000000000..b69e665c2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Node.cc @@ -0,0 +1,1512 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MVRTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::MVRTree; + +// +// Tools::IObject interface +// +Tools::IObject* Node::clone() +{ + throw Tools::NotSupportedException("IObject::clone should never be called."); +} + +// +// Tools::ISerializable interface +// +uint32_t Node::getByteArraySize() +{ + return + (sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(double) + + sizeof(double) + + (m_children * (m_pTree->m_dimension * sizeof(double) * 2 + sizeof(id_type) + 2 * sizeof(double) + sizeof(uint32_t))) + + m_totalDataLength + + (2 * m_pTree->m_dimension * sizeof(double))); +} + +void Node::loadFromByteArray(const byte* ptr) +{ + m_nodeMBR = m_pTree->m_infiniteRegion; + + // skip the node type information, it is not needed. + ptr += sizeof(uint32_t); + + memcpy(&m_level, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&m_children, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&(m_nodeMBR.m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(m_nodeMBR.m_endTime), ptr, sizeof(double)); + ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_ptrMBR[cChild] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[cChild]) = m_pTree->m_infiniteRegion; + + memcpy(m_ptrMBR[cChild]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(&(m_pIdentifier[cChild]), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&(m_ptrMBR[cChild]->m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(m_ptrMBR[cChild]->m_endTime), ptr, sizeof(double)); + ptr += sizeof(double); + + memcpy(&(m_pDataLength[cChild]), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + m_totalDataLength += m_pDataLength[cChild]; + m_pData[cChild] = new byte[m_pDataLength[cChild]]; + memcpy(m_pData[cChild], ptr, m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + else + { + m_pData[cChild] = 0; + } + + //m_nodeMBR.combineRegion(*(m_ptrMBR[cChild])); + } + + memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +void Node::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + + *data = new byte[len]; + byte* ptr = *data; + + uint32_t nodeType; + + if (m_level == 0) nodeType = PersistentLeaf; + else nodeType = PersistentIndex; + + memcpy(ptr, &nodeType, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_level, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_children, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &(m_nodeMBR.m_startTime), sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(m_nodeMBR.m_endTime), sizeof(double)); + ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + memcpy(ptr, m_ptrMBR[cChild]->m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, &(m_pIdentifier[cChild]), sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &(m_ptrMBR[cChild]->m_startTime), sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(m_ptrMBR[cChild]->m_endTime), sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, &(m_pDataLength[cChild]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + memcpy(ptr, m_pData[cChild], m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + } + + // store the node MBR for efficiency. This increases the node size a little bit. + memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +// +// SpatialIndex::IEntry interface +// +SpatialIndex::id_type Node::getIdentifier() const +{ + return m_identifier; +} + +void Node::getShape(IShape** out) const +{ + *out = new TimeRegion(m_nodeMBR); +} + +// +// SpatialIndex::INode interface +// +uint32_t Node::getChildrenCount() const +{ + return m_children; +} + +SpatialIndex::id_type Node::getChildIdentifier(uint32_t index) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + return m_pIdentifier[index]; +} + +void Node::getChildShape(uint32_t index, IShape** out) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + *out = new TimeRegion(*(m_ptrMBR[index])); +} + + +void Node::getChildData(uint32_t index, uint32_t& length, byte** data) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + if (m_pData[index] == NULL) + { + length = 0; + data = NULL; + } + else + { + length = m_pDataLength[index]; + *data = m_pData[index]; + } +} + +uint32_t Node::getLevel() const +{ + return m_level; +} + +bool Node::isLeaf() const +{ + return (m_level == 0); +} + +bool Node::isIndex() const +{ + return (m_level != 0); +} + +// +// Internal +// + +Node::Node() : + m_pTree(0), + m_level(0), + m_identifier(-1), + m_children(0), + m_capacity(0), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ +} + + Node::Node(SpatialIndex::MVRTree::MVRTree* pTree, id_type id, uint32_t level, uint32_t capacity) : + m_pTree(pTree), + m_level(level), + m_identifier(id), + m_children(0), + m_capacity(capacity), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ + m_nodeMBR.makeInfinite(m_pTree->m_dimension); + + try + { + m_pDataLength = new uint32_t[m_capacity + 2]; + m_pData = new byte*[m_capacity + 2]; + m_ptrMBR = new TimeRegionPtr[m_capacity + 2]; + m_pIdentifier = new id_type[m_capacity + 2]; + } + catch (...) + { + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + throw; + } +} + +Node::~Node() +{ + if (m_pData != 0) + { + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_pData[cChild] != 0) delete[] m_pData[cChild]; + } + + delete[] m_pData; + delete[] m_pDataLength; + } + + if (m_ptrMBR != 0) delete[] m_ptrMBR; + if (m_pIdentifier != 0) delete[] m_pIdentifier; +} + +Node& Node::operator=(const Node& n) +{ + throw Tools::IllegalStateException("operator =: This should never be called."); +} + +void Node::insertEntry(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id) +{ + assert(m_children < m_capacity); + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + m_totalDataLength += dataLength; + ++m_children; + + m_nodeMBR.combineRegionInTime(mbr); +} + +bool Node::deleteEntry(uint32_t index) +{ + assert(index >= 0 && index < m_children); + + // cache it, since I might need it for "touches" later. + TimeRegionPtr ptrR = m_ptrMBR[index]; + + m_totalDataLength -= m_pDataLength[index]; + if (m_pData[index] != 0) delete[] m_pData[index]; + + if (m_children > 1 && index != m_children - 1) + { + m_pDataLength[index] = m_pDataLength[m_children - 1]; + m_pData[index] = m_pData[m_children - 1]; + m_ptrMBR[index] = m_ptrMBR[m_children - 1]; + m_pIdentifier[index] = m_pIdentifier[m_children - 1]; + } + + --m_children; + + // WARNING: index has now changed. Do not use it below here. + + if (m_children == 0) + { + m_nodeMBR = m_pTree->m_infiniteRegion; + return true; + } + else if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesShape(*ptrR)) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + return true; + } + + return false; +} + +bool Node::insertData( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2, bool bForceAdjust) +{ + // we should be certain that when bInsertMbr2 is true the node needs to be version split + + // this function returns true only if the node under modification has been stored (writeNode(this)) + // it is needed since some times after a version copy we do not need to actually store the node. Only + // the parent has to be notified to modify the entry pointing + // to this node with the appropriate deletion time (thus we save one disk access) + + if ((! bInsertMbr2) && m_children < m_capacity) + { + // the node has empty space. Insert the entry here + + // this has to happen before insertEntry modifies m_nodeMBR. + bool b = m_nodeMBR.containsShape(mbr); + + insertEntry(dataLength, pData, mbr, id); + m_pTree->writeNode(this); + + // a forced adjust might be needed when a child has modified it MBR due to an entry deletion + // (when the entry start time becomes equal to the entry end time after a version copy) + if ((! b || bForceAdjust) && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } + + return true; + } + else + { + // do a version copy + + bool bIsRoot = pathBuffer.empty(); + + NodePtr ptrCopy; + + // copy live entries of this node into a new node. Create an index or a leaf respectively + if (m_level == 0) + { + ptrCopy = m_pTree->m_leafPool.acquire(); + if (ptrCopy.get() == 0) ptrCopy = NodePtr(new Leaf(m_pTree, - 1), &(m_pTree->m_leafPool)); + else ptrCopy->m_nodeMBR = m_pTree->m_infiniteRegion; + } + else + { + ptrCopy = m_pTree->m_indexPool.acquire(); + if (ptrCopy.get() == 0) ptrCopy = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + else + { + ptrCopy->m_level = m_level; + ptrCopy->m_nodeMBR = m_pTree->m_infiniteRegion; + } + } + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (! (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max())) + { + byte* data = 0; + + if (m_pDataLength[cChild] > 0) + { + data = new byte[m_pDataLength[cChild]]; + memcpy(data, m_pData[cChild], m_pDataLength[cChild] * sizeof(byte)); + } + ptrCopy->insertEntry(m_pDataLength[cChild], data, *(m_ptrMBR[cChild]), m_pIdentifier[cChild]); + ptrCopy->m_ptrMBR[ptrCopy->m_children - 1]->m_startTime = mbr.m_startTime; + } + } + + ptrCopy->m_nodeMBR.m_startTime = mbr.m_startTime; + m_nodeMBR.m_endTime = mbr.m_startTime; + + uint32_t children = (bInsertMbr2) ? ptrCopy->m_children + 2 : ptrCopy->m_children + 1; + assert(children > 0); + + if (children >= m_pTree->m_strongVersionOverflow * m_capacity) + { + // strong version overflow. Split! + NodePtr n; + NodePtr nn; + ptrCopy->split(dataLength, pData, mbr, id, n, nn, mbr2, id2, bInsertMbr2); + assert(n->m_children > 1 && nn->m_children > 1); + + if (bIsRoot) + { + // it is a root node. Special handling required. + n->m_level = ptrCopy->m_level; + nn->m_level = ptrCopy->m_level; + n->m_identifier = -1; + nn->m_identifier = -1; + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + NodePtr ptrR = m_pTree->m_indexPool.acquire(); + if (ptrR.get() == 0) ptrR = NodePtr(new Index(m_pTree, -1, ptrCopy->m_level + 1), &(m_pTree->m_indexPool)); + else + { + //ptrR->m_pTree = m_pTree; + //ptrR->m_identifier = -1; + ptrR->m_level = ptrCopy->m_level + 1; + ptrR->m_nodeMBR = m_pTree->m_infiniteRegion; + } + + ptrR->insertEntry(0, 0, n->m_nodeMBR, n->m_identifier); + ptrR->insertEntry(0, 0, nn->m_nodeMBR, nn->m_identifier); + + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + ptrR->m_identifier = m_identifier; + m_pTree->writeNode(ptrR.get()); + m_pTree->m_stats.m_treeHeight[m_pTree->m_stats.m_treeHeight.size() - 1] = ptrR->m_level + 1; + m_pTree->m_stats.m_nodesInLevel.at(n->m_level) = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 1; + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime == ptrCopy->m_nodeMBR.m_startTime && + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime == ptrCopy->m_nodeMBR.m_endTime); + } + else + { + m_pTree->writeNode(this); + m_pTree->writeNode(ptrR.get()); + + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_id == m_identifier); + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime = m_nodeMBR.m_startTime; + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime = m_nodeMBR.m_endTime; + m_pTree->m_roots.push_back(MVRTree::RootEntry(ptrR->m_identifier, ptrR->m_nodeMBR.m_startTime, ptrR->m_nodeMBR.m_endTime)); + m_pTree->m_stats.m_treeHeight.push_back(ptrR->m_level + 1); + m_pTree->m_stats.m_nodesInLevel.at(n->m_level) = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 2; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + } + + if (ptrR->m_level >= m_pTree->m_stats.m_nodesInLevel.size()) m_pTree->m_stats.m_nodesInLevel.push_back(1); + else m_pTree->m_stats.m_nodesInLevel.at(ptrR->m_level) = m_pTree->m_stats.m_nodesInLevel[ptrR->m_level] + 1; + + return true; + } + else + { + bool b = false; + + n->m_level = ptrCopy->m_level; + nn->m_level = ptrCopy->m_level; +/* + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + n->m_identifier = m_identifier; + m_pTree->m_stats.m_nodesInLevel[n->m_level] = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 1; + b = true; + } + else + { + n->m_identifier = -1; + m_pTree->m_stats.m_nodesInLevel[n->m_level] = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 2; + } +*/ + n->m_identifier = -1; + nn->m_identifier = -1; + + m_pTree->m_stats.m_nodesInLevel.at(n->m_level) = m_pTree->m_stats.m_nodesInLevel[n->m_level] + 2; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + ++(m_pTree->m_stats.m_u64Adjustments); + + // this is the special insertion function for two new nodes, defined below + p->insertData(n->m_nodeMBR, n->m_identifier, nn->m_nodeMBR, nn->m_identifier, this, pathBuffer); + + return b; + } + } + //else if (children < m_pTree->m_strongVersionUnderflow * m_capacity) + //{ + // do not do this for now + //} + else + { + // the entry contains the appropriate number of live entries + + ptrCopy->insertEntry(dataLength, pData, mbr, id); + if (bInsertMbr2) ptrCopy->insertEntry(0, 0, mbr2, id2); + + if (bIsRoot) + { + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + ptrCopy->m_identifier = m_identifier; + m_pTree->writeNode(ptrCopy.get()); + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime == ptrCopy->m_nodeMBR.m_startTime && + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime == ptrCopy->m_nodeMBR.m_endTime); + } + else + { + m_pTree->writeNode(ptrCopy.get()); + m_pTree->writeNode(this); + + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_id == m_identifier); + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime = m_nodeMBR.m_startTime; + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime = m_nodeMBR.m_endTime; + m_pTree->m_roots.push_back(MVRTree::RootEntry(ptrCopy->m_identifier, ptrCopy->m_nodeMBR.m_startTime, ptrCopy->m_nodeMBR.m_endTime)); + m_pTree->m_stats.m_treeHeight.push_back(ptrCopy->m_level + 1); + + m_pTree->m_stats.m_nodesInLevel.at(ptrCopy->m_level) = m_pTree->m_stats.m_nodesInLevel[ptrCopy->m_level] + 1; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + } + + return true; + } + else + { + m_pTree->writeNode(ptrCopy.get()); + + m_pTree->m_stats.m_nodesInLevel.at(ptrCopy->m_level) = m_pTree->m_stats.m_nodesInLevel[ptrCopy->m_level] + 1; + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + ++(m_pTree->m_stats.m_u64Adjustments); + + uint32_t child; + for (child = 0; child < p->m_children; ++child) + { + if (p->m_pIdentifier[child] == m_identifier) break; + } + + // it might be needed to update the MBR since the child MBR might have changed + // from an entry deletion (from insertData, below, when m_startTime == m_endTime) + double st = p->m_ptrMBR[child]->m_startTime; + *(p->m_ptrMBR[child]) = m_nodeMBR; + p->m_ptrMBR[child]->m_startTime = st; + //p->m_ptrMBR[child]->m_endTime = mbr.m_startTime; + + // insert this new version copy into the parent + p->insertData(0, 0, ptrCopy->m_nodeMBR, ptrCopy->m_identifier, pathBuffer, m_pTree->m_infiniteRegion, -1, false); + + return false; + } + } + } +} + +void Node::insertData(TimeRegion& mbr1, id_type id1, TimeRegion& mbr2, id_type id2, Node* oldVersion, std::stack<id_type>& pathBuffer) +{ + // this should be called only from insertData above + // it tries to fit two new entries into the node + + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == oldVersion->m_identifier) break; + } + + // save the original node MBR + bool bAdjust = false; + TimeRegionPtr ptrR = m_pTree->m_regionPool.acquire(); + *ptrR = m_nodeMBR; + + // it might be needed to update the MBR since the child MBR might have changed + // from an entry deletion (when m_startTime == m_endTime) + double st = m_ptrMBR[child]->m_startTime; + *(m_ptrMBR[child]) = oldVersion->m_nodeMBR; + m_ptrMBR[child]->m_startTime = st; + //m_ptrMBR[child]->m_endTime = oldVersion->m_nodeMBR.m_endTime; + + if (m_children < m_capacity - 1) + { + // there is enough space for both new entries + + insertEntry(0, 0, mbr1, id1); + insertEntry(0, 0, mbr2, id2); + + m_pTree->writeNode(this); + + if ((! pathBuffer.empty()) && (bAdjust || ! (ptrR->containsShape(mbr1) && ptrR->containsShape(mbr2)))) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } + } + else + { + // call a normal insertData which will trigger a version copy + // insertData will adjust the parent since this node will certainly do a version copy + bool bStored = insertData(0, 0, mbr1, id1, pathBuffer, mbr2, id2, true); + if (! bStored) m_pTree->writeNode(this); + } +} + +bool Node::deleteData(id_type id, double delTime, std::stack<id_type>& pathBuffer, bool bForceAdjust) +{ + // it returns true if a new root has been created because all the entries of the old root have died. + // This is needed in case the root dies while there are pending reinsertions from multiple levels + + uint32_t child = m_capacity; + uint32_t alive = 0; + bool bAdjustParent = false; + TimeRegionPtr oldNodeMBR = m_pTree->m_regionPool.acquire(); + *oldNodeMBR = m_nodeMBR; + NodePtr parent; + + // make sure that there are no "snapshot" entries + // find how many children are alive and locate the entry to be deleted + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_level != 0 || (m_ptrMBR[cChild]->m_startTime != m_ptrMBR[cChild]->m_endTime)); + if (! (m_ptrMBR[cChild]->m_endTime < std::numeric_limits<double>::max())) ++alive; + if (m_pIdentifier[cChild] == id) child = cChild; + } + + assert(child < m_capacity); + + // either make the entry dead or, if its start time is equal to the deletion time, + // delete it from the node completely (in which case the parent MBR might need adjustment) + bool bAdjusted = false; + + if (m_level == 0 && m_ptrMBR[child]->m_startTime == delTime) + { + bAdjusted = deleteEntry(child); + bAdjustParent = bAdjusted; + } + else + { + m_ptrMBR[child]->m_endTime = delTime; + } + + // if it has not been adjusted yet (by deleteEntry) and it should be adjusted, do it. + // a forced adjustment is needed when a child node has adjusted its own MBR and signals + // the parent to adjust it, also. + if ((! bAdjusted) && bForceAdjust) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + // signal our parent to adjust its MBR also + bAdjustParent = true; + } + + // one less live entry from now on + --alive; + + if (alive < m_pTree->m_versionUnderflow * m_capacity && (! pathBuffer.empty())) + { + // if the weak version condition is broken, try to resolve it + // if this is a leaf and it can still hold some entries (since all entries might be dead now and + // the node full) try to borrow a live entry from a sibling + // [Yufei Tao, Dimitris Papadias, 'MV3R-Tree: A Spatio-Temporal Access Method for Timestamp and + // Interval Queries', Section 3.3] + if (m_level == 0 && m_children < m_capacity) + { + parent = m_pTree->readNode(pathBuffer.top()); + pathBuffer.pop(); + + // find us in our parent + for (child = 0; child < parent->m_children; ++child) + { + if (parent->m_pIdentifier[child] == m_identifier) break; + } + + // remember that the parent might be younger than us, pointing to us through a pointer + // created with a version copy. So the actual start time of this node through the path + // from the root might actually be different than the stored start time. + double actualNodeStartTime = parent->m_ptrMBR[child]->m_startTime; + + // find an appropriate sibling + for (uint32_t cSibling = 0; cSibling < parent->m_children; ++cSibling) + { + // it has to be different than us, it has to be alive and its MBR should intersect ours + if ( + parent->m_pIdentifier[cSibling] != m_identifier && + ! (parent->m_ptrMBR[cSibling]->m_endTime < std::numeric_limits<double>::max()) && + parent->m_ptrMBR[cSibling]->intersectsShape(m_nodeMBR)) + { + NodePtr sibling = m_pTree->readNode(parent->m_pIdentifier[cSibling]); + std::vector<DeleteDataEntry> toCheck; + alive = 0; + + // if this child does not have a single parent, we cannot borrow an entry. + bool bSingleParent = true; + + for (uint32_t cSiblingChild = 0; cSiblingChild < sibling->m_children; ++cSiblingChild) + { + // if the insertion time of any child is smaller than the starting time stored in the + // parent of this node than the node has more than one parent + if (sibling->m_ptrMBR[cSiblingChild]->m_startTime < parent->m_ptrMBR[cSibling]->m_startTime) + { + bSingleParent = false; + break; + } + + // find the live sibling entries, and also the ones that can be moved to this node + // sort them by area enlargement + if (! (sibling->m_ptrMBR[cSiblingChild]->m_endTime < std::numeric_limits<double>::max())) + { + ++alive; + if (sibling->m_ptrMBR[cSiblingChild]->m_startTime >= actualNodeStartTime) + { + TimeRegionPtr tmpR = m_pTree->m_regionPool.acquire(); + *tmpR = m_nodeMBR; + tmpR->combineRegion(*(sibling->m_ptrMBR[cSiblingChild])); + double a = tmpR->getArea(); + if (a <= m_nodeMBR.getArea() * 1.1) toCheck.push_back(DeleteDataEntry(cSiblingChild, a)); + } + } + } + + // if the sibling has more than one parent or if we cannot remove an entry because we will + // cause a weak version overflow, this sibling is not appropriate + if ((! bSingleParent) || toCheck.empty() || alive == m_pTree->m_versionUnderflow * sibling->m_capacity + 1) continue; + + // create interval counters for checking weak version condition + // [Yufei Tao, Dimitris Papadias, 'MV3R-Tree: A Spatio-Temporal Access Method for Timestamp and + // Interval Queries', Section 3.2] + std::set<double> Si; + for (uint32_t cSiblingChild = 0; cSiblingChild < sibling->m_children; ++cSiblingChild) + { + Si.insert(sibling->m_ptrMBR[cSiblingChild]->m_startTime); + Si.insert(sibling->m_ptrMBR[cSiblingChild]->m_endTime); + } + // duplicate entries have been removed and the set is sorted + uint32_t* SiCounts = new uint32_t[Si.size() - 1]; + bzero(SiCounts, (Si.size() - 1) * sizeof(uint32_t)); + + for (uint32_t cSiblingChild = 0; cSiblingChild < sibling->m_children; ++cSiblingChild) + { + std::set<double>::iterator it1 = Si.begin(); + std::set<double>::iterator it2 = Si.begin(); + for (size_t cIndex = 0; cIndex < Si.size() - 1; ++cIndex) + { + ++it2; + if ( + sibling->m_ptrMBR[cSiblingChild]->m_startTime <= *it1 && + sibling->m_ptrMBR[cSiblingChild]->m_endTime >= *it2 + ) ++(SiCounts[cIndex]); + ++it1; + } + } + + std::vector<DeleteDataEntry> Sdel; + + for (size_t cCheck = 0; cCheck < toCheck.size(); ++cCheck) + { + bool good = true; + + // check if it can be removed without a weak version underflow + std::set<double>::iterator it1 = Si.begin(); + std::set<double>::iterator it2 = Si.begin(); + for (size_t cIndex = 0; cIndex < Si.size() - 1; ++cIndex) + { + ++it2; + if ( + sibling->m_ptrMBR[toCheck[cCheck].m_index]->m_startTime <= *it1 && + sibling->m_ptrMBR[toCheck[cCheck].m_index]->m_endTime >= *it2 && + SiCounts[cIndex] <= m_pTree->m_versionUnderflow * sibling->m_capacity) + { + good = false; + break; + } + ++it1; + } + if (good) Sdel.push_back(toCheck[cCheck]); + } + + delete[] SiCounts; + + if (Sdel.empty()) continue; + + // we found some entries. Sort them according to least enlargement, insert the best entry into + // this node, remove it from the sibling and update the MBRs of the parent + + sort(Sdel.begin(), Sdel.end(), DeleteDataEntry::compare); + uint32_t entry = Sdel[0].m_index; + bool b1 = m_nodeMBR.containsShape(*(sibling->m_ptrMBR[entry])); + bool b2 = sibling->m_nodeMBR.touchesShape(*(sibling->m_ptrMBR[entry])); + + insertEntry(sibling->m_pDataLength[entry], sibling->m_pData[entry], *(sibling->m_ptrMBR[entry]), sibling->m_pIdentifier[entry]); + sibling->m_pData[entry] = 0; + + // the weak version condition check above, guarantees that. + assert(sibling->m_children > 1); + sibling->deleteEntry(entry); + + m_pTree->writeNode(this); + m_pTree->writeNode(sibling.get()); + + Index* p = static_cast<Index*>(parent.get()); + if (((! b1) || bAdjustParent) && b2) p->adjustTree(this, sibling.get(), pathBuffer); + else if ((! b1) || bAdjustParent) p->adjustTree(this, pathBuffer); + else if (b2) p->adjustTree(sibling.get(), pathBuffer); + + return false; + } + } + } + + // either this is not a leaf, or an appropriate sibling was not found, so make this node dead + // and reinsert all live entries from the root + m_nodeMBR.m_endTime = delTime; + m_pTree->writeNode(this); + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + if (parent.get() == 0) + { + parent = m_pTree->readNode(pathBuffer.top()); + pathBuffer.pop(); + } + + if (bAdjustParent) + { + // the correct child pointer might have been calculated already from earlier + if (child < parent->m_children && m_identifier != parent->m_pIdentifier[child]) + { + for (child = 0; child < parent->m_children; ++child) + { + if (parent->m_pIdentifier[child] == m_identifier) break; + } + } + + // both start time and end time should be preserved since deleteData below needs + // to know how many entries where alive, including this one + double st = parent->m_ptrMBR[child]->m_startTime; + double en = parent->m_ptrMBR[child]->m_endTime; + *(parent->m_ptrMBR[child]) = m_nodeMBR; + parent->m_ptrMBR[child]->m_startTime = st; + parent->m_ptrMBR[child]->m_endTime = en; + } + + // delete this node from the parent node. + // if this node had been adjusted and its old MBR was touching the parent MBR, the + // parent MBR needs to be adjusted also. + // the deletion has to happen first, since the reinsertions might modify the path to this node + bool bNewRoot = parent->deleteData(m_identifier, delTime, pathBuffer, (bAdjustParent && parent->m_nodeMBR.touchesShape(*oldNodeMBR))); + + // reinsert all the live entries from the root + + // normally I should not modify any node instances, since writeNode might be caching nodes + // in main memory, even though I have persisted them, so I have to make copies + + // this code will try and reinsert whole paths if possible. It might be the case, though, + // that a root died, which means that all the live data entries have to be scanned and reinserted themselves + for (child = 0; child < m_children; ++child) + { + if (! (m_ptrMBR[child]->m_endTime < std::numeric_limits<double>::max())) + { + if (! bNewRoot || m_level == 0) + { + m_ptrMBR[child]->m_startTime = delTime; + m_pTree->insertData_impl(m_pDataLength[child], m_pData[child], *(m_ptrMBR[child]), m_pIdentifier[child], m_level); + // make sure we do not delete the data array from this node's destructor + m_pData[child] = 0; + } + else + { + std::stack<NodePtr> Sins; + Sins.push(m_pTree->readNode(m_pIdentifier[child])); + while (! Sins.empty()) + { + NodePtr p = Sins.top(); Sins.pop(); + if (p->m_level == 0) + { + for (uint32_t cIndex= 0; cIndex < p->m_children; ++cIndex) + { + if (! (p->m_ptrMBR[cIndex]->m_endTime < std::numeric_limits<double>::max())) + { + p->m_ptrMBR[cIndex]->m_startTime = delTime; + m_pTree->insertData_impl(p->m_pDataLength[cIndex], p->m_pData[cIndex], *(p->m_ptrMBR[cIndex]), p->m_pIdentifier[cIndex], p->m_level); + // make sure we do not delete the data array from this node's destructor + p->m_pData[cIndex] = 0; + } + } + } + else + { + for (uint32_t cIndex= 0; cIndex < p->m_children; ++cIndex) + { + if (! (p->m_ptrMBR[cIndex]->m_endTime < std::numeric_limits<double>::max())) + { + Sins.push(m_pTree->readNode(p->m_pIdentifier[cIndex])); + } + } + } + } + } + } + } + } + else + { + // either this is a root node or there is no weak version condition + + if (alive == 0 && pathBuffer.empty()) + { + if (m_children > 0) + { + // all root children are dead. Create a new root + m_nodeMBR.m_endTime = delTime; + m_pTree->m_bHasVersionCopied = false; + + if (m_nodeMBR.m_startTime == m_nodeMBR.m_endTime) + { + Leaf root(m_pTree, m_identifier); + root.m_nodeMBR.m_startTime = m_nodeMBR.m_endTime; + root.m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + m_pTree->writeNode(&root); + + m_pTree->m_stats.m_treeHeight[m_pTree->m_stats.m_treeHeight.size() - 1] = 1; + if (m_pTree->m_stats.m_nodesInLevel.at(m_level) == 1) m_pTree->m_stats.m_nodesInLevel.pop_back(); + else m_pTree->m_stats.m_nodesInLevel.at(m_level) = m_pTree->m_stats.m_nodesInLevel[m_level] - 1; + m_pTree->m_stats.m_nodesInLevel.at(0) = m_pTree->m_stats.m_nodesInLevel[0] + 1; + } + else + { + m_pTree->writeNode(this); + + if (m_level > 0) ++(m_pTree->m_stats.m_u32DeadIndexNodes); + else ++(m_pTree->m_stats.m_u32DeadLeafNodes); + + Leaf root(m_pTree, -1); + root.m_nodeMBR.m_startTime = m_nodeMBR.m_endTime; + root.m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + m_pTree->writeNode(&root); + assert(m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_id == m_identifier); + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_startTime = m_nodeMBR.m_startTime; + m_pTree->m_roots[m_pTree->m_roots.size() - 1].m_endTime = m_nodeMBR.m_endTime; + m_pTree->m_roots.push_back(MVRTree::RootEntry(root.m_identifier, root.m_nodeMBR.m_startTime, root.m_nodeMBR.m_endTime)); + + m_pTree->m_stats.m_treeHeight.push_back(1); + m_pTree->m_stats.m_nodesInLevel.at(root.m_level) = m_pTree->m_stats.m_nodesInLevel[root.m_level] + 1; + } + return true; + } + else + { + assert(m_level == 0); + m_pTree->writeNode(this); + m_pTree->m_bHasVersionCopied = false; + return false; + } + } + else if (bAdjustParent && (! pathBuffer.empty())) + { + // the parent needs to be adjusted + m_pTree->writeNode(this); + parent = m_pTree->readNode(pathBuffer.top()); + pathBuffer.pop(); + Index* p = static_cast<Index*>(parent.get()); + p->adjustTree(this, pathBuffer); + } + else + { + m_pTree->writeNode(this); + } + } + + return false; +} + +void Node::rtreeSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + uint32_t cChild; + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + uint32_t cTotal = (bInsertMbr2) ? m_children + 2 : m_children + 1; + + // use this mask array for marking visited entries. + byte* mask = new byte[cTotal]; + bzero(mask, cTotal); + + // insert new data in the node for easier manipulation. Data arrays are always + // by two larger than node capacity. + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + if (bInsertMbr2) + { + m_pDataLength[m_children + 1] = 0; + m_pData[m_children + 1] = 0; + m_ptrMBR[m_children + 1] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children + 1]) = mbr2; + m_pIdentifier[m_children + 1] = id2; + } + + // initialize each group with the seed entries. + uint32_t seed1, seed2; + pickSeeds(seed1, seed2, cTotal); + + group1.push_back(seed1); + group2.push_back(seed2); + + mask[seed1] = 1; + mask[seed2] = 1; + + // find MBR of each group. + TimeRegionPtr mbrA = m_pTree->m_regionPool.acquire(); + *mbrA = *(m_ptrMBR[seed1]); + TimeRegionPtr mbrB = m_pTree->m_regionPool.acquire(); + *mbrB = *(m_ptrMBR[seed2]); + + // count how many entries are left unchecked (exclude the seeds here.) + uint32_t cRemaining = cTotal - 2; + + while (cRemaining > 0) + { + if (minimumLoad - group1.size() == cRemaining) + { + // all remaining entries must be assigned to group1 to comply with minimun load requirement. + for (cChild = 0; cChild < cTotal; ++cChild) + { + if (mask[cChild] == 0) + { + group1.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else if (minimumLoad - group2.size() == cRemaining) + { + // all remaining entries must be assigned to group2 to comply with minimun load requirement. + for (cChild = 0; cChild < cTotal; ++cChild) + { + if (mask[cChild] == 0) + { + group2.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else + { + // For all remaining entries compute the difference of the cost of grouping an + // entry in either group. When done, choose the entry that yielded the maximum + // difference. In case of linear split, select any entry (e.g. the first one.) + uint32_t sel; + double md1 = 0.0, md2 = 0.0; + double m = -std::numeric_limits<double>::max(); + double d1, d2, d; + double a1 = mbrA->getArea(); + double a2 = mbrB->getArea(); + + TimeRegionPtr a = m_pTree->m_regionPool.acquire(); + TimeRegionPtr b = m_pTree->m_regionPool.acquire(); + + for (cChild = 0; cChild < cTotal; ++cChild) + { + if (mask[cChild] == 0) + { + mbrA->getCombinedRegion(*a, *(m_ptrMBR[cChild])); + d1 = a->getArea() - a1; + mbrB->getCombinedRegion(*b, *(m_ptrMBR[cChild])); + d2 = b->getArea() - a2; + d = std::abs(d1 - d2); + + if (d > m) + { + m = d; + md1 = d1; md2 = d2; + sel = cChild; + if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break; + } + } + } + + // determine the group where we should add the new entry. + int32_t group = 1; + + if (md1 < md2) + { + group1.push_back(sel); + group = 1; + } + else if (md2 < md1) + { + group2.push_back(sel); + group = 2; + } + else if (a1 < a2) + { + group1.push_back(sel); + group = 1; + } + else if (a2 < a1) + { + group2.push_back(sel); + group = 2; + } + else if (group1.size() < group2.size()) + { + group1.push_back(sel); + group = 1; + } + else if (group2.size() < group1.size()) + { + group2.push_back(sel); + group = 2; + } + else + { + group1.push_back(sel); + group = 1; + } + mask[sel] = 1; + --cRemaining; + if (group == 1) + { + mbrA->combineRegion(*(m_ptrMBR[sel])); + } + else + { + mbrB->combineRegion(*(m_ptrMBR[sel])); + } + } + } + + delete[] mask; +} + +void Node::rstarSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2) +{ + RstarSplitEntry** dataLow = 0; + RstarSplitEntry** dataHigh = 0; + + uint32_t cTotal = (bInsertMbr2) ? m_children + 2 : m_children + 1; + + try + { + dataLow = new RstarSplitEntry*[cTotal]; + dataHigh = new RstarSplitEntry*[cTotal]; + } + catch (...) + { + delete[] dataLow; + throw; + } + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + if (bInsertMbr2) + { + m_pDataLength[m_children + 1] = 0; + m_pData[m_children + 1] = 0; + m_ptrMBR[m_children + 1] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children + 1]) = mbr2; + m_pIdentifier[m_children + 1] = id2; + } + + uint32_t nodeSPF = static_cast<uint32_t>(std::floor(cTotal * m_pTree->m_splitDistributionFactor)); + uint32_t splitDistribution = cTotal - (2 * nodeSPF) + 2; + + uint32_t cChild = 0, cDim, cIndex; + + for (cChild = 0; cChild < cTotal; ++cChild) + { + try + { + dataLow[cChild] = new RstarSplitEntry(m_ptrMBR[cChild].get(), cChild, 0); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete dataLow[i]; + delete[] dataLow; + delete[] dataHigh; + throw; + } + + dataHigh[cChild] = dataLow[cChild]; + } + + double minimumMargin = std::numeric_limits<double>::max(); + uint32_t splitAxis = std::numeric_limits<uint32_t>::max(); + uint32_t sortOrder = std::numeric_limits<uint32_t>::max(); + + // chooseSplitAxis. + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + ::qsort(dataLow, + cTotal, + sizeof(RstarSplitEntry*), + RstarSplitEntry::compareLow); + + ::qsort(dataHigh, + cTotal, + sizeof(RstarSplitEntry*), + RstarSplitEntry::compareHigh); + + // calculate sum of margins and overlap for all distributions. + double marginl = 0.0; + double marginh = 0.0; + + TimeRegion bbl1, bbl2, bbh1, bbh2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bbl1 = *(dataLow[0]->m_pRegion); + bbh1 = *(dataHigh[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bbl1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh1.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + bbl2 = *(dataLow[l]->m_pRegion); + bbh2 = *(dataHigh[l]->m_pRegion); + + for (cIndex = l + 1; cIndex < cTotal; ++cIndex) + { + bbl2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh2.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + marginl += bbl1.getMargin() + bbl2.getMargin(); + marginh += bbh1.getMargin() + bbh2.getMargin(); + } // for (cChild) + + double margin = std::min(marginl, marginh); + + // keep minimum margin as split axis. + if (margin < minimumMargin) + { + minimumMargin = margin; + splitAxis = cDim; + sortOrder = (marginl < marginh) ? 0 : 1; + } + + // increase the dimension according to which the data entries should be sorted. + for (cChild = 0; cChild < cTotal; ++cChild) + { + dataLow[cChild]->m_sortDim = cDim + 1; + } + } // for (cDim) + + for (cChild = 0; cChild < cTotal; ++cChild) + { + dataLow[cChild]->m_sortDim = splitAxis; + } + + ::qsort( + dataLow, + cTotal, + sizeof(RstarSplitEntry*), + (sortOrder == 0) ? RstarSplitEntry::compareLow : RstarSplitEntry::compareHigh); + + double ma = std::numeric_limits<double>::max(); + double mo = std::numeric_limits<double>::max(); + uint32_t splitPoint = std::numeric_limits<uint32_t>::max(); + + TimeRegion bb1, bb2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bb1 = *(dataLow[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bb1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + bb2 = *(dataLow[l]->m_pRegion); + + for (cIndex = l + 1; cIndex < cTotal; ++cIndex) + { + bb2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + double o = bb1.getIntersectingArea(bb2); + + if (o < mo) + { + splitPoint = cChild; + mo = o; + ma = bb1.getArea() + bb2.getArea(); + } + else if (o == mo) + { + double a = bb1.getArea() + bb2.getArea(); + + if (a < ma) + { + splitPoint = cChild; + ma = a; + } + } + } // for (cChild) + + uint32_t l1 = nodeSPF - 1 + splitPoint; + + for (cIndex = 0; cIndex < l1; ++cIndex) + { + group1.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + for (cIndex = l1; cIndex < cTotal; ++cIndex) + { + group2.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + delete[] dataLow; + delete[] dataHigh; +} + +void Node::pickSeeds(uint32_t& index1, uint32_t& index2, uint32_t total) +{ + double separation = -std::numeric_limits<double>::max(); + double inefficiency = -std::numeric_limits<double>::max(); + uint32_t cDim, cChild, cIndex; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_RSTAR: + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + double leastLower = m_ptrMBR[0]->m_pLow[cDim]; + double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim]; + uint32_t greatestLower = 0; + uint32_t leastUpper = 0; + double width; + + for (cChild = 1; cChild < total; ++cChild) + { + if (m_ptrMBR[cChild]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = cChild; + if (m_ptrMBR[cChild]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = cChild; + + leastLower = std::min(m_ptrMBR[cChild]->m_pLow[cDim], leastLower); + greatestUpper = std::max(m_ptrMBR[cChild]->m_pHigh[cDim], greatestUpper); + } + + width = greatestUpper - leastLower; + if (width <= 0) width = 1; + + double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width; + + if (f > separation) + { + index1 = leastUpper; + index2 = greatestLower; + separation = f; + } + } // for (cDim) + + if (index1 == index2) + { + if (index2 == 0) ++index2; + else --index2; + } + + break; + case RV_QUADRATIC: + // for each pair of Regions (account for overflow Region too!) + for (cChild = 0; cChild < total - 1; ++cChild) + { + double a = m_ptrMBR[cChild]->getArea(); + + for (cIndex = cChild + 1; cIndex < total; ++cIndex) + { + // get the combined MBR of those two entries. + TimeRegion r; + m_ptrMBR[cChild]->getCombinedRegion(r, *(m_ptrMBR[cIndex])); + + // find the inefficiency of grouping these entries together. + double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea(); + + if (d > inefficiency) + { + inefficiency = d; + index1 = cChild; + index2 = cIndex; + } + } // for (cIndex) + } // for (cChild) + + break; + default: + throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported."); + } +} + +NodePtr Node::findNode(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_pIdentifier[cChild] == id) + return m_pTree->readNode(m_pIdentifier[cChild]); + + if (m_ptrMBR[cChild]->containsShape(mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findNode(mbr, id, pathBuffer); + assert(n.get() != l.get()); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Node.h b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Node.h new file mode 100644 index 000000000..187435e43 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Node.h @@ -0,0 +1,184 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class MVRTree; + class Leaf; + class Index; + class Node; + + typedef Tools::PoolPointer<Node> NodePtr; + + class Node : public SpatialIndex::INode + { + public: + virtual ~Node(); + + // + // Tools::IObject interface + // + virtual IObject* clone(); + + // + // Tools::ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // SpatialIndex::IEntry interface + // + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + + // + // SpatialIndex::INode interface + // + virtual uint32_t getChildrenCount() const; + virtual id_type getChildIdentifier(uint32_t index) const; + virtual void getChildShape(uint32_t index, IShape** out) const; + virtual void getChildData(uint32_t index, uint32_t& length, byte** data) const; + virtual uint32_t getLevel() const; + virtual bool isIndex() const; + virtual bool isLeaf() const; + + private: + Node(); + Node(MVRTree* pTree, id_type id, uint32_t level, uint32_t capacity); + + virtual Node& operator=(const Node&); + + virtual void insertEntry(uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id); + virtual bool deleteEntry(uint32_t index); + + virtual bool insertData( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false, bool forceAdjust = false); + virtual void insertData(TimeRegion& mbr1, id_type id1, TimeRegion& mbr2, id_type id2, Node* oldVersion, std::stack<id_type>& pathBuffer); + virtual bool deleteData(id_type id, double delTime, std::stack<id_type>& pathBuffer, bool adjustMBR = false); + + virtual void rtreeSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + virtual void rstarSplit( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false); + + virtual void pickSeeds(uint32_t& index1, uint32_t& index2, uint32_t total); + + virtual NodePtr chooseSubtree(const TimeRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findLeaf(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findNode(const TimeRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split( + uint32_t dataLength, byte* pData, TimeRegion& mbr, id_type id, NodePtr& left, NodePtr& right, + TimeRegion& mbr2, id_type id2, bool bInsertMbr2 = false) = 0; + + MVRTree* m_pTree; + // Parent of all nodes. + + uint32_t m_level; + // The level of the node in the tree. + // Leaves are always at level 0. + + id_type m_identifier; + // The unique ID of this node. + + uint32_t m_children; + // The number of children pointed by this node. + + uint32_t m_capacity; + // Specifies the node capacity. + + TimeRegion m_nodeMBR; + // The minimum bounding region enclosing all data contained in the node. + + byte** m_pData; + // The data stored in the node. + + TimeRegionPtr* m_ptrMBR; + // The corresponding data MBRs. + + id_type* m_pIdentifier; + // The corresponding data identifiers. + + uint32_t* m_pDataLength; + + uint32_t m_totalDataLength; + + class RstarSplitEntry + { + public: + RstarSplitEntry(TimeRegion* pr, uint32_t index, uint32_t dimension) : + m_pRegion(pr), m_index(index), m_sortDim(dimension) {} + + static int compareLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] < pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] > pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return 1; + return 0; + } + + static int compareHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return 1; + return 0; + } + + TimeRegion* m_pRegion; + uint32_t m_index; + uint32_t m_sortDim; + }; // RstarSplitEntry + + class DeleteDataEntry + { + public: + DeleteDataEntry(uint32_t index, double d) : m_index(index), m_increase(d) {} + + static bool compare(DeleteDataEntry e1, DeleteDataEntry e2) { return e1.m_increase < e2.m_increase; } + + uint32_t m_index; + double m_increase; + }; // DeleteDataEntry + + // Needed to access protected members without having to cast from Node. + // It is more efficient than using member functions to access protected members. + friend class MVRTree; + friend class Leaf; + friend class Index; + friend class Tools::PointerPool<Node>; + }; // Node + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/PointerPoolNode.h b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/PointerPoolNode.h new file mode 100644 index 000000000..33407df02 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/PointerPoolNode.h @@ -0,0 +1,133 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Node.h" + +namespace Tools +{ + template<> class PointerPool<SpatialIndex::MVRTree::Node> + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + SpatialIndex::MVRTree::Node* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<SpatialIndex::MVRTree::Node> acquire() + { + if (! m_pool.empty()) + { + SpatialIndex::MVRTree::Node* p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + ++m_hits; + #endif + + return PoolPointer<SpatialIndex::MVRTree::Node>(p, this); + } + #ifndef NDEBUG + else + { + // fixme: well sort of... + ++m_pointerCount; + ++m_misses; + } + #endif + + return PoolPointer<SpatialIndex::MVRTree::Node>(); + } + + void release(SpatialIndex::MVRTree::Node* p) + { + if (p != 0) + { + if (m_pool.size() < m_capacity) + { + if (p->m_pData != 0) + { + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + if (p->m_pData[cChild] != 0) delete[] p->m_pData[cChild]; + } + } + + p->m_level = 0; + p->m_identifier = -1; + p->m_children = 0; + p->m_totalDataLength = 0; + + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + protected: + uint32_t m_capacity; + std::stack<SpatialIndex::MVRTree::Node*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Statistics.cc b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Statistics.cc new file mode 100644 index 000000000..3ffbcefae --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Statistics.cc @@ -0,0 +1,191 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Statistics.h" + +using namespace SpatialIndex::MVRTree; + +Statistics::Statistics() +{ + reset(); +} + +Statistics::Statistics(const Statistics& s) +{ + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u32DeadIndexNodes = s.m_u32DeadIndexNodes; + m_u32DeadLeafNodes = s.m_u32DeadLeafNodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u64TotalData = s.m_u64TotalData; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; +} + +Statistics::~Statistics() +{ +} + +Statistics& Statistics::operator=(const Statistics& s) +{ + if (this != &s) + { + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u32DeadIndexNodes = s.m_u32DeadIndexNodes; + m_u32DeadLeafNodes = s.m_u32DeadLeafNodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u64TotalData = s.m_u64TotalData; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; + } + + return *this; +} + +uint64_t Statistics::getReads() const +{ + return m_u64Reads; +} + +uint64_t Statistics::getWrites() const +{ + return m_u64Writes; +} + +uint32_t Statistics::getNumberOfNodes() const +{ + return m_u32Nodes; +} + +uint64_t Statistics::getNumberOfData() const +{ + return m_u64Data; +} + +uint64_t Statistics::getSplits() const +{ + return m_u64Splits; +} + +uint64_t Statistics::getHits() const +{ + return m_u64Hits; +} + +uint64_t Statistics::getMisses() const +{ + return m_u64Misses; +} + +uint64_t Statistics::getAdjustments() const +{ + return m_u64Adjustments; +} + +uint64_t Statistics::getQueryResults() const +{ + return m_u64QueryResults; +} + +uint32_t Statistics::getTreeHeight() const +{ + uint32_t ret = 0; + + for (size_t cIndex = 0; cIndex < m_treeHeight.size(); ++cIndex) + { + ret = std::max(ret, m_treeHeight[cIndex]); + } + + return ret; +} + +uint32_t Statistics::getNumberOfNodesInLevel(uint32_t l) const +{ + try + { + return m_nodesInLevel.at(l); + } + catch (...) + { + throw Tools::IndexOutOfBoundsException(l); + } +} + +void Statistics::reset() +{ + m_u64Reads = 0; + m_u64Writes = 0; + m_u64Splits = 0; + m_u64Hits = 0; + m_u64Misses = 0; + m_u32Nodes = 0; + m_u32DeadIndexNodes = 0; + m_u32DeadLeafNodes = 0; + m_u64Adjustments = 0; + m_u64QueryResults = 0; + m_u64Data = 0; + m_u64TotalData = 0; + m_treeHeight.clear(); + m_nodesInLevel.clear(); +} + +std::ostream& SpatialIndex::MVRTree::operator<<(std::ostream& os, const Statistics& s) +{ + os << "Reads: " << s.m_u64Reads << std::endl + << "Writes: " << s.m_u64Writes << std::endl + << "Hits: " << s.m_u64Hits << std::endl + << "Misses: " << s.m_u64Misses << std::endl + << "Number of live data: " << s.m_u64Data << std::endl + << "Total number of data: " << s.m_u64TotalData << std::endl + << "Number of nodes: " << s.m_u32Nodes << std::endl + << "Numer of dead index nodes: " << s.m_u32DeadIndexNodes << std::endl + << "Numer of dead leaf nodes: " << s.m_u32DeadLeafNodes << std::endl; + + for (size_t cTree = 0; cTree < s.m_treeHeight.size(); ++cTree) + { + os << "Tree " << cTree << ", Height " << s.m_treeHeight[cTree] << std::endl; + } + + for (size_t cLevel = 0; cLevel < s.m_nodesInLevel.size(); ++cLevel) + { + os << "Level " << cLevel << " pages: " << s.m_nodesInLevel[cLevel] << std::endl; + } + + os << "Splits: " << s.m_u64Splits << std::endl + << "Adjustments: " << s.m_u64Adjustments << std::endl + << "Query results: " << s.m_u64QueryResults << std::endl; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Statistics.h b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Statistics.h new file mode 100644 index 000000000..249a98cac --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/mvrtree/Statistics.h @@ -0,0 +1,99 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace MVRTree + { + class MVRTree; + class Node; + class Leaf; + class Index; + + class Statistics : public SpatialIndex::IStatistics + { + public: + Statistics(); + Statistics(const Statistics&); + virtual ~Statistics(); + Statistics& operator=(const Statistics&); + + // + // IStatistics interface + // + virtual uint64_t getReads() const; + virtual uint64_t getWrites() const; + virtual uint32_t getNumberOfNodes() const; + virtual uint64_t getNumberOfData() const; + + virtual uint64_t getSplits() const; + virtual uint64_t getHits() const; + virtual uint64_t getMisses() const; + virtual uint64_t getAdjustments() const; + virtual uint64_t getQueryResults() const; + virtual uint32_t getTreeHeight() const; + virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const; + + private: + void reset(); + + uint64_t m_u64Reads; + + uint64_t m_u64Writes; + + uint64_t m_u64Splits; + + uint64_t m_u64Hits; + + uint64_t m_u64Misses; + + uint32_t m_u32Nodes; + + uint32_t m_u32DeadIndexNodes; + + uint32_t m_u32DeadLeafNodes; + + uint64_t m_u64Adjustments; + + uint64_t m_u64QueryResults; + + uint64_t m_u64Data; + + uint64_t m_u64TotalData; + + std::vector<uint32_t> m_treeHeight; + + std::vector<uint32_t> m_nodesInLevel; + + friend class MVRTree; + friend class Node; + friend class Index; + friend class Leaf; + + friend std::ostream& operator<<(std::ostream& os, const Statistics& s); + }; // Statistics + + std::ostream& operator<<(std::ostream& os, const Statistics& s); + } +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/all-wcprops new file mode 100644 index 000000000..064065c70 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/all-wcprops @@ -0,0 +1,89 @@ +K 25 +svn:wc:ra_dav:version-url +V 55 +/spatialindex/!svn/ver/181/spatialindex/trunk/src/rtree +END +Statistics.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/Statistics.h +END +RTree.cc +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/rtree/RTree.cc +END +PointerPoolNode.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/PointerPoolNode.h +END +RTree.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/133/spatialindex/trunk/src/rtree/RTree.h +END +BulkLoader.cc +K 25 +svn:wc:ra_dav:version-url +V 69 +/spatialindex/!svn/ver/181/spatialindex/trunk/src/rtree/BulkLoader.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/45/spatialindex/trunk/src/rtree/Makefile.am +END +Node.cc +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/rtree/Node.cc +END +BulkLoader.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/132/spatialindex/trunk/src/rtree/BulkLoader.h +END +Index.cc +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/rtree/Index.cc +END +Leaf.cc +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/Leaf.cc +END +Node.h +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/Node.h +END +Index.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/Index.h +END +Leaf.h +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/Leaf.h +END +Statistics.cc +K 25 +svn:wc:ra_dav:version-url +V 69 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/rtree/Statistics.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/dir-prop-base new file mode 100644 index 000000000..ea9b95e8a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/dir-prop-base @@ -0,0 +1,9 @@ +K 10 +svn:ignore +V 33 +Makefile.in +.libs +.deps +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/entries new file mode 100644 index 000000000..a74e15d59 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/entries @@ -0,0 +1,504 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/rtree +http://svn.gispython.org/spatialindex + + + +2010-04-12T17:07:13.774013Z +181 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Statistics.h +file + + + + +2011-08-01T00:42:34.549134Z +94cda4c818ca1f8fb5df3636155f1819 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2293 + +RTree.cc +file + + + + +2011-08-01T00:42:34.549134Z +a74add8050d27a9000c9c1c888c55e5a +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +43344 + +PointerPoolNode.h +file + + + + +2011-08-01T00:42:34.549134Z +31296acf2a6c706a54f63b8cd48de5e2 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +3015 + +RTree.h +file + + + + +2011-08-01T00:42:34.549134Z +eab591c68b607cb7ef47ad3fe537a92f +2009-08-14T15:19:40.553411Z +133 +hobu + + + + + + + + + + + + + + + + + + + + + +6821 + +BulkLoader.cc +file + + + + +2011-08-01T00:42:34.549134Z +46d2cff70e12f219e608643fb7b5dd7e +2010-04-12T17:07:13.774013Z +181 +mhadji + + + + + + + + + + + + + + + + + + + + + +11307 + +Makefile.am +file + + + + +2011-08-01T00:42:34.549134Z +1d38b85a74c38e0ec673a16952349697 +2008-01-17T23:34:01.575758Z +45 +hobu + + + + + + + + + + + + + + + + + + + + + +292 + +Node.cc +file + + + + +2011-08-01T00:42:34.549134Z +8ff5747378f669668ff10a1fd50f544a +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +28187 + +BulkLoader.h +file + + + + +2011-08-01T00:42:34.553152Z +e7ab0daf9fbba3f120bd7c92595f9061 +2009-08-13T19:10:02.395894Z +132 +mhadji + + + + + + + + + + + + + + + + + + + + + +3195 + +Index.cc +file + + + + +2011-08-01T00:42:34.553152Z +df5cd482aeed566ba127b36ad268b374 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +10474 + +Leaf.cc +file + + + + +2011-08-01T00:42:34.553152Z +319461954ec844a6c37547bb57e7e3a5 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +4268 + +Node.h +file + + + + +2011-08-01T00:42:34.553152Z +95ebf90b30308c1f27bcac12fa6a2948 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +5954 + +Index.h +file + + + + +2011-08-01T00:42:34.553152Z +2cdb5447b856942f246d29240996bf2d +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2170 + +Leaf.h +file + + + + +2011-08-01T00:42:34.553152Z +c6f78b493a99573bad11f79b9e6ead4e +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +1461 + +Statistics.cc +file + + + + +2011-08-01T00:42:34.553152Z +1354a1c5c0d19bef42dea03eff069ab4 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +3817 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/BulkLoader.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/BulkLoader.cc.svn-base new file mode 100644 index 000000000..5fb14963d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/BulkLoader.cc.svn-base @@ -0,0 +1,458 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <stdio.h> +#include <cmath> + +#ifndef _MSC_VER +#include <unistd.h> +#endif + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Leaf.h" +#include "Index.h" +#include "BulkLoader.h" + +using namespace SpatialIndex::RTree; + +// +// ExternalSorter::Record +// +ExternalSorter::Record::Record() +: m_pData(0) +{ +} + +ExternalSorter::Record::Record(const Region& r, id_type id, uint32_t len, byte* pData, uint32_t s) +: m_r(r), m_id(id), m_len(len), m_pData(pData), m_s(s) +{ +} + +ExternalSorter::Record::~Record() +{ + delete[] m_pData; +} + +bool ExternalSorter::Record::operator<(const Record& r) const +{ + if (m_s != r.m_s) + throw Tools::IllegalStateException("ExternalSorter::Record::operator<: Incompatible sorting dimensions."); + + if (m_r.m_pHigh[m_s] + m_r.m_pLow[m_s] < r.m_r.m_pHigh[m_s] + r.m_r.m_pLow[m_s]) + return true; + else + return false; +} + +void ExternalSorter::Record::storeToFile(Tools::TemporaryFile& f) +{ + f.write(static_cast<uint64_t>(m_id)); + f.write(m_r.m_dimension); + f.write(m_s); + + for (uint32_t i = 0; i < m_r.m_dimension; ++i) + { + f.write(m_r.m_pLow[i]); + f.write(m_r.m_pHigh[i]); + } + + f.write(m_len); + if (m_len > 0) f.write(m_len, m_pData); +} + +void ExternalSorter::Record::loadFromFile(Tools::TemporaryFile& f) +{ + m_id = static_cast<id_type>(f.readUInt64()); + uint32_t dim = f.readUInt32(); + m_s = f.readUInt32(); + + if (dim != m_r.m_dimension) + { + delete[] m_r.m_pLow; + delete[] m_r.m_pHigh; + m_r.m_dimension = dim; + m_r.m_pLow = new double[dim]; + m_r.m_pHigh = new double[dim]; + } + + for (uint32_t i = 0; i < m_r.m_dimension; ++i) + { + m_r.m_pLow[i] = f.readDouble(); + m_r.m_pHigh[i] = f.readDouble(); + } + + m_len = f.readUInt32(); + delete[] m_pData; m_pData = 0; + if (m_len > 0) f.readBytes(m_len, &m_pData); +} + +// +// ExternalSorter +// +ExternalSorter::ExternalSorter(uint32_t u32PageSize, uint32_t u32BufferPages) +: m_bInsertionPhase(true), m_u32PageSize(u32PageSize), + m_u32BufferPages(u32BufferPages), m_u64TotalEntries(0), m_stI(0) +{ +} + +ExternalSorter::~ExternalSorter() +{ + for (m_stI = 0; m_stI < m_buffer.size(); ++m_stI) delete m_buffer[m_stI]; +} + +void ExternalSorter::insert(Record* r) +{ + if (m_bInsertionPhase == false) + throw Tools::IllegalStateException("ExternalSorter::insert: Input has already been sorted."); + + m_buffer.push_back(r); + ++m_u64TotalEntries; + + // this will create the initial, sorted buckets before the + // external merge sort. + if (m_buffer.size() >= m_u32PageSize * m_u32BufferPages) + { + std::sort(m_buffer.begin(), m_buffer.end(), Record::SortAscending()); + Tools::TemporaryFile* tf = new Tools::TemporaryFile(); + for (size_t j = 0; j < m_buffer.size(); ++j) + { + m_buffer[j]->storeToFile(*tf); + delete m_buffer[j]; + } + m_buffer.clear(); + tf->rewindForReading(); + m_runs.push_back(Tools::SmartPointer<Tools::TemporaryFile>(tf)); + } +} + +void ExternalSorter::sort() +{ + if (m_bInsertionPhase == false) + throw Tools::IllegalStateException("ExternalSorter::sort: Input has already been sorted."); + + if (m_runs.empty()) + { + // The data fits in main memory. No need to store to disk. + std::sort(m_buffer.begin(), m_buffer.end(), Record::SortAscending()); + m_bInsertionPhase = false; + return; + } + + if (m_buffer.size() > 0) + { + // Whatever remained in the buffer (if not filled) needs to be stored + // as the final bucket. + std::sort(m_buffer.begin(), m_buffer.end(), Record::SortAscending()); + Tools::TemporaryFile* tf = new Tools::TemporaryFile(); + for (size_t j = 0; j < m_buffer.size(); ++j) + { + m_buffer[j]->storeToFile(*tf); + delete m_buffer[j]; + } + m_buffer.clear(); + tf->rewindForReading(); + m_runs.push_back(Tools::SmartPointer<Tools::TemporaryFile>(tf)); + } + + if (m_runs.size() == 1) + { + m_sortedFile = m_runs.front(); + } + else + { + Record* r; + + while (m_runs.size() > 1) + { + Tools::SmartPointer<Tools::TemporaryFile> tf(new Tools::TemporaryFile()); + std::vector<Tools::SmartPointer<Tools::TemporaryFile> > buckets; + std::vector<std::queue<Record*> > buffers; + std::priority_queue<PQEntry, std::vector<PQEntry>, PQEntry::SortAscending> pq; + + // initialize buffers and priority queue. + std::list<Tools::SmartPointer<Tools::TemporaryFile> >::iterator it = m_runs.begin(); + for (uint32_t i = 0; i < (std::min)(static_cast<uint32_t>(m_runs.size()), m_u32BufferPages); ++i) + { + buckets.push_back(*it); + buffers.push_back(std::queue<Record*>()); + + r = new Record(); + r->loadFromFile(**it); + // a run cannot be empty initially, so this should never fail. + pq.push(PQEntry(r, i)); + + for (uint32_t j = 0; j < m_u32PageSize - 1; ++j) + { + // fill the buffer with the rest of the page of records. + try + { + r = new Record(); + r->loadFromFile(**it); + buffers.back().push(r); + } + catch (Tools::EndOfStreamException) + { + delete r; + break; + } + } + ++it; + } + + // exhaust buckets, buffers, and priority queue. + while (! pq.empty()) + { + PQEntry e = pq.top(); pq.pop(); + e.m_r->storeToFile(*tf); + delete e.m_r; + + if (! buckets[e.m_u32Index]->eof() && buffers[e.m_u32Index].empty()) + { + for (uint32_t j = 0; j < m_u32PageSize; ++j) + { + try + { + r = new Record(); + r->loadFromFile(*buckets[e.m_u32Index]); + buffers[e.m_u32Index].push(r); + } + catch (Tools::EndOfStreamException) + { + delete r; + break; + } + } + } + + if (! buffers[e.m_u32Index].empty()) + { + e.m_r = buffers[e.m_u32Index].front(); + buffers[e.m_u32Index].pop(); + pq.push(e); + } + } + + tf->rewindForReading(); + + // check if another pass is needed. + uint32_t u32Count = std::min(static_cast<uint32_t>(m_runs.size()), m_u32BufferPages); + for (uint32_t i = 0; i < u32Count; ++i) + { + m_runs.pop_front(); + } + + if (m_runs.size() == 0) + { + m_sortedFile = tf; + break; + } + else + { + m_runs.push_back(tf); + } + } + } + + m_bInsertionPhase = false; +} + +ExternalSorter::Record* ExternalSorter::getNextRecord() +{ + if (m_bInsertionPhase == true) + throw Tools::IllegalStateException("ExternalSorter::getNextRecord: Input has not been sorted yet."); + + Record* ret; + + if (m_sortedFile.get() == 0) + { + if (m_stI < m_buffer.size()) + { + ret = m_buffer[m_stI]; + m_buffer[m_stI] = 0; + ++m_stI; + } + else + throw Tools::EndOfStreamException(""); + } + else + { + ret = new Record(); + ret->loadFromFile(*m_sortedFile); + } + + return ret; +} + +inline uint64_t ExternalSorter::getTotalEntries() const +{ + return m_u64TotalEntries; +} + +// +// BulkLoader +// +void BulkLoader::bulkLoadUsingSTR( + SpatialIndex::RTree::RTree* pTree, + IDataStream& stream, + uint32_t bindex, + uint32_t bleaf, + uint32_t pageSize, + uint32_t numberOfPages +) { + if (! stream.hasNext()) + throw Tools::IllegalArgumentException( + "RTree::BulkLoader::bulkLoadUsingSTR: Empty data stream given." + ); + + NodePtr n = pTree->readNode(pTree->m_rootID); + pTree->deleteNode(n.get()); + + #ifndef NDEBUG + std::cerr << "RTree::BulkLoader: Sorting data." << std::endl; + #endif + + Tools::SmartPointer<ExternalSorter> es = Tools::SmartPointer<ExternalSorter>(new ExternalSorter(pageSize, numberOfPages)); + + while (stream.hasNext()) + { + Data* d = reinterpret_cast<Data*>(stream.getNext()); + if (d == 0) + throw Tools::IllegalArgumentException( + "bulkLoadUsingSTR: RTree bulk load expects SpatialIndex::RTree::Data entries." + ); + + es->insert(new ExternalSorter::Record(d->m_region, d->m_id, d->m_dataLength, d->m_pData, 0)); + d->m_pData = 0; + delete d; + } + es->sort(); + + pTree->m_stats.m_u64Data = es->getTotalEntries(); + + // create index levels. + uint32_t level = 0; + + while (true) + { + #ifndef NDEBUG + std::cerr << "RTree::BulkLoader: Building level " << level << std::endl; + #endif + + pTree->m_stats.m_nodesInLevel.push_back(0); + + Tools::SmartPointer<ExternalSorter> es2 = Tools::SmartPointer<ExternalSorter>(new ExternalSorter(pageSize, numberOfPages)); + createLevel(pTree, es, 0, bleaf, bindex, level++, es2, pageSize, numberOfPages); + es = es2; + + if (es->getTotalEntries() == 1) break; + es->sort(); + } + + pTree->m_stats.m_u32TreeHeight = level; + pTree->storeHeader(); +} + +void BulkLoader::createLevel( + SpatialIndex::RTree::RTree* pTree, + Tools::SmartPointer<ExternalSorter> es, + uint32_t dimension, + uint32_t bleaf, + uint32_t bindex, + uint32_t level, + Tools::SmartPointer<ExternalSorter> es2, + uint32_t pageSize, + uint32_t numberOfPages +) { + uint64_t b = (level == 0) ? bleaf : bindex; + uint64_t P = static_cast<uint64_t>(std::ceil(static_cast<double>(es->getTotalEntries()) / static_cast<double>(b))); + uint64_t S = static_cast<uint64_t>(std::ceil(std::sqrt(static_cast<double>(P)))); + + if (S == 1 || dimension == pTree->m_dimension - 1 || S * b == es->getTotalEntries()) + { + std::vector<ExternalSorter::Record*> node; + ExternalSorter::Record* r; + + while (true) + { + try { r = es->getNextRecord(); } catch (Tools::EndOfStreamException) { break; } + node.push_back(r); + + if (node.size() == b) + { + Node* n = createNode(pTree, node, level); + node.clear(); + pTree->writeNode(n); + es2->insert(new ExternalSorter::Record(n->m_nodeMBR, n->m_identifier, 0, 0, 0)); + pTree->m_rootID = n->m_identifier; + // special case when the root has exactly bindex entries. + delete n; + } + } + + if (! node.empty()) + { + Node* n = createNode(pTree, node, level); + pTree->writeNode(n); + es2->insert(new ExternalSorter::Record(n->m_nodeMBR, n->m_identifier, 0, 0, 0)); + pTree->m_rootID = n->m_identifier; + delete n; + } + } + else + { + bool bMore = true; + + while (bMore) + { + ExternalSorter::Record* pR; + Tools::SmartPointer<ExternalSorter> es3 = Tools::SmartPointer<ExternalSorter>(new ExternalSorter(pageSize, numberOfPages)); + + for (uint64_t i = 0; i < S * b; ++i) + { + try { pR = es->getNextRecord(); } + catch (Tools::EndOfStreamException) { bMore = false; break; } + pR->m_s = dimension + 1; + es3->insert(pR); + } + es3->sort(); + createLevel(pTree, es3, dimension + 1, bleaf, bindex, level, es2, pageSize, numberOfPages); + } + } +} + +Node* BulkLoader::createNode(SpatialIndex::RTree::RTree* pTree, std::vector<ExternalSorter::Record*>& e, uint32_t level) +{ + Node* n; + + if (level == 0) n = new Leaf(pTree, -1); + else n = new Index(pTree, -1, level); + + for (size_t cChild = 0; cChild < e.size(); ++cChild) + { + n->insertEntry(e[cChild]->m_len, e[cChild]->m_pData, e[cChild]->m_r, e[cChild]->m_id); + e[cChild]->m_pData = 0; + delete e[cChild]; + } + + return n; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/BulkLoader.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/BulkLoader.h.svn-base new file mode 100644 index 000000000..17d8f71fb --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/BulkLoader.h.svn-base @@ -0,0 +1,131 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class ExternalSorter + { + public: + class Record + { + public: + Record(); + Record(const Region& r, id_type id, uint32_t len, byte* pData, uint32_t s); + ~Record(); + + bool operator<(const Record& r) const; + + void storeToFile(Tools::TemporaryFile& f); + void loadFromFile(Tools::TemporaryFile& f); + + struct SortAscending : public std::binary_function<Record* const, Record* const, bool> + { + bool operator()(Record* const r1, Record* const r2) + { + if (*r1 < *r2) return true; + else return false; + } + }; + + public: + Region m_r; + id_type m_id; + byte* m_pData; + uint32_t m_len; + uint32_t m_s; + }; + + public: + ExternalSorter(uint32_t u32PageSize, uint32_t u32BufferPages); + virtual ~ExternalSorter(); + + void insert(Record* r); + void sort(); + Record* getNextRecord(); + uint64_t getTotalEntries() const; + + private: + class PQEntry + { + public: + PQEntry(Record* r, uint32_t u32Index) : m_r(r), m_u32Index(u32Index) {} + + struct SortAscending : public std::binary_function<const PQEntry&, const PQEntry&, bool> + { + bool operator()(const PQEntry& e1, const PQEntry& e2) + { + if (*(e1.m_r) < *(e2.m_r)) return true; + else return false; + } + }; + + Record* m_r; + uint32_t m_u32Index; + }; + + private: + bool m_bInsertionPhase; + uint32_t m_u32PageSize; + uint32_t m_u32BufferPages; + Tools::SmartPointer<Tools::TemporaryFile> m_sortedFile; + std::list<Tools::SmartPointer<Tools::TemporaryFile> > m_runs; + std::vector<Record*> m_buffer; + uint64_t m_u64TotalEntries; + uint32_t m_stI; + }; + + class BulkLoader + { + public: + void bulkLoadUsingSTR( + RTree* pTree, + IDataStream& stream, + uint32_t bindex, + uint32_t bleaf, + uint32_t pageSize, // The number of node entries per page. + uint32_t numberOfPages // The total number of pages to use. + ); + + protected: + void createLevel( + RTree* pTree, + Tools::SmartPointer<ExternalSorter> es, + uint32_t dimension, + uint32_t indexSize, + uint32_t leafSize, + uint32_t level, + Tools::SmartPointer<ExternalSorter> es2, + uint32_t pageSize, + uint32_t numberOfPages + ); + + Node* createNode( + RTree* pTree, + std::vector<ExternalSorter::Record*>& e, + uint32_t level + ); + }; + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Index.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Index.cc.svn-base new file mode 100644 index 000000000..9a3209683 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Index.cc.svn-base @@ -0,0 +1,372 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" + +using namespace SpatialIndex::RTree; + +Index::~Index() +{ +} + +Index::Index(SpatialIndex::RTree::RTree* pTree, id_type id, uint32_t level) : Node(pTree, id, level, pTree->m_indexCapacity) +{ +} + +NodePtr Index::chooseSubtree(const Region& mbr, uint32_t insertionLevel, std::stack<id_type>& pathBuffer) +{ + if (m_level == insertionLevel) return NodePtr(this, &(m_pTree->m_indexPool)); + + pathBuffer.push(m_identifier); + + uint32_t child = 0; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + child = findLeastEnlargement(mbr); + break; + case RV_RSTAR: + if (m_level == 1) + { + // if this node points to leaves... + child = findLeastOverlap(mbr); + } + else + { + child = findLeastEnlargement(mbr); + } + break; + default: + throw Tools::NotSupportedException("Index::chooseSubtree: Tree variant not supported."); + } + assert(child != std::numeric_limits<uint32_t>::max()); + + NodePtr n = m_pTree->readNode(m_pIdentifier[child]); + NodePtr ret = n->chooseSubtree(mbr, insertionLevel, pathBuffer); + assert(n.unique()); + if (ret.get() == n.get()) n.relinquish(); + + return ret; +} + +NodePtr Index::findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_ptrMBR[cChild]->containsRegion(mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findLeaf(mbr, id, pathBuffer); + if (n.get() == l.get()) n.relinquish(); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} + +void Index::split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& ptrLeft, NodePtr& ptrRight) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Index::split: Tree variant not supported."); + } + + ptrLeft = m_pTree->m_indexPool.acquire(); + ptrRight = m_pTree->m_indexPool.acquire(); + + if (ptrLeft.get() == 0) ptrLeft = NodePtr(new Index(m_pTree, m_identifier, m_level), &(m_pTree->m_indexPool)); + if (ptrRight.get() == 0) ptrRight = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + + ptrLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + ptrRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + ptrLeft->insertEntry(0, 0, *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + ptrRight->insertEntry(0, 0, *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + } +} + +uint32_t Index::findLeastEnlargement(const Region& r) const +{ + double area = std::numeric_limits<double>::max(); + uint32_t best = std::numeric_limits<uint32_t>::max(); + + RegionPtr t = m_pTree->m_regionPool.acquire(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_ptrMBR[cChild]->getCombinedRegion(*t, r); + + double a = m_ptrMBR[cChild]->getArea(); + double enl = t->getArea() - a; + + if (enl < area) + { + area = enl; + best = cChild; + } + else if (enl == area) + { + // this will rarely happen, so compute best area on the fly only + // when necessary. + if (a < m_ptrMBR[best]->getArea()) best = cChild; + } + } + + return best; +} + +uint32_t Index::findLeastOverlap(const Region& r) const +{ + OverlapEntry** entries = new OverlapEntry*[m_children]; + + double leastOverlap = std::numeric_limits<double>::max(); + double me = std::numeric_limits<double>::max(); + OverlapEntry* best = 0; + + // find combined region and enlargement of every entry and store it. + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + try + { + entries[cChild] = new OverlapEntry(); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete entries[i]; + delete[] entries; + throw; + } + + entries[cChild]->m_index = cChild; + entries[cChild]->m_original = m_ptrMBR[cChild]; + entries[cChild]->m_combined = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->getCombinedRegion(*(entries[cChild]->m_combined), r); + entries[cChild]->m_oa = entries[cChild]->m_original->getArea(); + entries[cChild]->m_ca = entries[cChild]->m_combined->getArea(); + entries[cChild]->m_enlargement = entries[cChild]->m_ca - entries[cChild]->m_oa; + + if (entries[cChild]->m_enlargement < me) + { + me = entries[cChild]->m_enlargement; + best = entries[cChild]; + } + else if (entries[cChild]->m_enlargement == me && entries[cChild]->m_oa < best->m_oa) + { + best = entries[cChild]; + } + } + + if (me < -std::numeric_limits<double>::epsilon() || me > std::numeric_limits<double>::epsilon()) + { + uint32_t cIterations; + + if (m_children > m_pTree->m_nearMinimumOverlapFactor) + { + // sort entries in increasing order of enlargement. + ::qsort(entries, m_children, + sizeof(OverlapEntry*), + OverlapEntry::compareEntries); + assert(entries[0]->m_enlargement <= entries[m_children - 1]->m_enlargement); + + cIterations = m_pTree->m_nearMinimumOverlapFactor; + } + else + { + cIterations = m_children; + } + + // calculate overlap of most important original entries (near minimum overlap cost). + for (uint32_t cIndex = 0; cIndex < cIterations; ++cIndex) + { + double dif = 0.0; + OverlapEntry* e = entries[cIndex]; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (e->m_index != cChild) + { + double f = e->m_combined->getIntersectingArea(*(m_ptrMBR[cChild])); + if (f != 0.0) dif += f - e->m_original->getIntersectingArea(*(m_ptrMBR[cChild])); + } + } // for (cChild) + + if (dif < leastOverlap) + { + leastOverlap = dif; + best = entries[cIndex]; + } + else if (dif == leastOverlap) + { + if (e->m_enlargement == best->m_enlargement) + { + // keep the one with least area. + if (e->m_original->getArea() < best->m_original->getArea()) best = entries[cIndex]; + } + else + { + // keep the one with least enlargement. + if (e->m_enlargement < best->m_enlargement) best = entries[cIndex]; + } + } + } // for (cIndex) + } + + uint32_t ret = best->m_index; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + delete entries[cChild]; + } + delete[] entries; + + return ret; +} + +void Index::adjustTree(Node* n, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n->m_identifier) break; + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + bool bContained = m_nodeMBR.containsRegion(n->m_nodeMBR); + bool bTouches = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool bRecompute = (! bContained || (bTouches && m_pTree->m_bTightMBRs)); + + *(m_ptrMBR[child]) = n->m_nodeMBR; + + if (bRecompute) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + m_pTree->writeNode(this); + + if (bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} + +void Index::adjustTree(Node* n1, Node* n2, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n1->m_identifier) break; + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + bool bContained = m_nodeMBR.containsRegion(n1->m_nodeMBR); + bool bTouches = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool bRecompute = (! bContained || (bTouches && m_pTree->m_bTightMBRs)); + + *(m_ptrMBR[child]) = n1->m_nodeMBR; + + if (bRecompute) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + // No write necessary here. insertData will write the node if needed. + //m_pTree->writeNode(this); + + bool bAdjusted = insertData(0, 0, n2->m_nodeMBR, n2->m_identifier, pathBuffer, overflowTable); + + // if n2 is contained in the node and there was no split or reinsert, + // we need to adjust only if recalculation took place. + // In all other cases insertData above took care of adjustment. + if ((! bAdjusted) && bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Index.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Index.h.svn-base new file mode 100644 index 000000000..ce0510dff --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Index.h.svn-base @@ -0,0 +1,73 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class Index : public Node + { + public: + virtual ~Index(); + + protected: + Index(RTree* pTree, id_type id, uint32_t level); + + virtual NodePtr chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& left, NodePtr& right); + + uint32_t findLeastEnlargement(const Region&) const; + uint32_t findLeastOverlap(const Region&) const; + + void adjustTree(Node*, std::stack<id_type>&); + void adjustTree(Node*, Node*, std::stack<id_type>&, byte* overflowTable); + + class OverlapEntry + { + public: + uint32_t m_index; + double m_enlargement; + RegionPtr m_original; + RegionPtr m_combined; + double m_oa; + double m_ca; + + static int compareEntries(const void* pv1, const void* pv2) + { + OverlapEntry* pe1 = * (OverlapEntry**) pv1; + OverlapEntry* pe2 = * (OverlapEntry**) pv2; + + if (pe1->m_enlargement < pe2->m_enlargement) return -1; + if (pe1->m_enlargement > pe2->m_enlargement) return 1; + return 0; + } + }; // OverlapEntry + + friend class RTree; + friend class Node; + friend class BulkLoader; + }; // Index + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Leaf.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Leaf.cc.svn-base new file mode 100644 index 000000000..5781734d5 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Leaf.cc.svn-base @@ -0,0 +1,138 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::RTree; + +Leaf::~Leaf() +{ +} + +Leaf::Leaf(SpatialIndex::RTree::RTree* pTree, id_type id): Node(pTree, id, 0, pTree->m_leafCapacity) +{ +} + +NodePtr Leaf::chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer) +{ + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + return NodePtr(this, &(m_pTree->m_leafPool)); +} + +NodePtr Leaf::findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + if (m_pIdentifier[cChild] == id && mbr == *(m_ptrMBR[cChild])) return NodePtr(this, &(m_pTree->m_leafPool)); + } + + return NodePtr(); +} + +void Leaf::split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Leaf::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_leafPool.acquire(); + pRight = m_pTree->m_leafPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + if (pRight.get() == 0) pRight = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(m_pDataLength[g1[cIndex]], m_pData[g1[cIndex]], *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g1[cIndex]] = 0; + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(m_pDataLength[g2[cIndex]], m_pData[g2[cIndex]], *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g2[cIndex]] = 0; + } +} + +void Leaf::deleteData(id_type id, std::stack<id_type>& pathBuffer) +{ + uint32_t child; + + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == id) break; + } + + deleteEntry(child); + m_pTree->writeNode(this); + + std::stack<NodePtr> toReinsert; + NodePtr ptrThis(this, &(m_pTree->m_leafPool)); + condenseTree(toReinsert, pathBuffer, ptrThis); + ptrThis.relinquish(); + + // re-insert eliminated nodes. + while (! toReinsert.empty()) + { + NodePtr n = toReinsert.top(); toReinsert.pop(); + m_pTree->deleteNode(n.get()); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + // keep this in the for loop. The tree height might change after insertions. + byte* overflowTable = new byte[m_pTree->m_stats.m_u32TreeHeight]; + bzero(overflowTable, m_pTree->m_stats.m_u32TreeHeight); + m_pTree->insertData_impl(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild], n->m_level, overflowTable); + n->m_pData[cChild] = 0; + delete[] overflowTable; + } + if (n.get() == this) n.relinquish(); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Leaf.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Leaf.h.svn-base new file mode 100644 index 000000000..2705e4c1d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Leaf.h.svn-base @@ -0,0 +1,47 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class Leaf : public Node + { + public: + virtual ~Leaf(); + + protected: + Leaf(RTree* pTree, id_type id); + + virtual NodePtr chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& left, NodePtr& right); + + virtual void deleteData(id_type id, std::stack<id_type>& pathBuffer); + + friend class RTree; + friend class BulkLoader; + }; // Leaf + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..e1bcd6272 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = librtree.la +INCLUDES = -I../../include +librtree_la_SOURCES = BulkLoader.cc Index.cc Leaf.cc Node.cc RTree.cc Statistics.cc BulkLoader.h Index.h Leaf.h Node.h PointerPoolNode.h RTree.h Statistics.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Node.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Node.cc.svn-base new file mode 100644 index 000000000..09ecfe943 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Node.cc.svn-base @@ -0,0 +1,1074 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Node.h" +#include "Index.h" + +using namespace SpatialIndex::RTree; + +// +// Tools::IObject interface +// +Tools::IObject* Node::clone() +{ + throw Tools::NotSupportedException("IObject::clone should never be called."); +} + +// +// Tools::ISerializable interface +// +uint32_t Node::getByteArraySize() +{ + return + (sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + (m_children * (m_pTree->m_dimension * sizeof(double) * 2 + sizeof(id_type) + sizeof(uint32_t))) + + m_totalDataLength + + (2 * m_pTree->m_dimension * sizeof(double))); +} + +void Node::loadFromByteArray(const byte* ptr) +{ + m_nodeMBR = m_pTree->m_infiniteRegion; + + // skip the node type information, it is not needed. + ptr += sizeof(uint32_t); + + memcpy(&m_level, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&m_children, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + m_ptrMBR[u32Child] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[u32Child]) = m_pTree->m_infiniteRegion; + + memcpy(m_ptrMBR[u32Child]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[u32Child]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(&(m_pIdentifier[u32Child]), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(&(m_pDataLength[u32Child]), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[u32Child] > 0) + { + m_totalDataLength += m_pDataLength[u32Child]; + m_pData[u32Child] = new byte[m_pDataLength[u32Child]]; + memcpy(m_pData[u32Child], ptr, m_pDataLength[u32Child]); + ptr += m_pDataLength[u32Child]; + } + else + { + m_pData[u32Child] = 0; + } + + //m_nodeMBR.combineRegion(*(m_ptrMBR[u32Child])); + } + + memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +void Node::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + + *data = new byte[len]; + byte* ptr = *data; + + uint32_t nodeType; + + if (m_level == 0) nodeType = PersistentLeaf; + else nodeType = PersistentIndex; + + memcpy(ptr, &nodeType, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_level, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_children, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + memcpy(ptr, m_ptrMBR[u32Child]->m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[u32Child]->m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, &(m_pIdentifier[u32Child]), sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(ptr, &(m_pDataLength[u32Child]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[u32Child] > 0) + { + memcpy(ptr, m_pData[u32Child], m_pDataLength[u32Child]); + ptr += m_pDataLength[u32Child]; + } + } + + // store the node MBR for efficiency. This increases the node size a little bit. + memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); + + assert(len == (ptr - *data) + m_pTree->m_dimension * sizeof(double)); +} + +// +// SpatialIndex::IEntry interface +// +SpatialIndex::id_type Node::getIdentifier() const +{ + return m_identifier; +} + +void Node::getShape(IShape** out) const +{ + *out = new Region(m_nodeMBR); +} + +// +// SpatialIndex::INode interface +// +uint32_t Node::getChildrenCount() const +{ + return m_children; +} + +SpatialIndex::id_type Node::getChildIdentifier(uint32_t index) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + return m_pIdentifier[index]; +} + +void Node::getChildShape(uint32_t index, IShape** out) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + *out = new Region(*(m_ptrMBR[index])); +} + +void Node::getChildData(uint32_t index, uint32_t& length, byte** data) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + if (m_pData[index] == NULL) + { + length = 0; + data = NULL; + } + else + { + length = m_pDataLength[index]; + *data = m_pData[index]; + } +} + +uint32_t Node::getLevel() const +{ + return m_level; +} + +bool Node::isLeaf() const +{ + return (m_level == 0); +} + +bool Node::isIndex() const +{ + return (m_level != 0); +} + +// +// Internal +// + +Node::Node() : + m_pTree(0), + m_level(0), + m_identifier(-1), + m_children(0), + m_capacity(0), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ +} + +Node::Node(SpatialIndex::RTree::RTree* pTree, id_type id, uint32_t level, uint32_t capacity) : + m_pTree(pTree), + m_level(level), + m_identifier(id), + m_children(0), + m_capacity(capacity), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ + m_nodeMBR.makeInfinite(m_pTree->m_dimension); + + try + { + m_pDataLength = new uint32_t[m_capacity + 1]; + m_pData = new byte*[m_capacity + 1]; + m_ptrMBR = new RegionPtr[m_capacity + 1]; + m_pIdentifier = new id_type[m_capacity + 1]; + } + catch (...) + { + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + throw; + } +} + +Node::~Node() +{ + if (m_pData != 0) + { + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + if (m_pData[u32Child] != 0) delete[] m_pData[u32Child]; + } + + delete[] m_pData; + } + + delete[] m_pDataLength; + delete[] m_ptrMBR; + delete[] m_pIdentifier; +} + +Node& Node::operator=(const Node& n) +{ + throw Tools::IllegalStateException("operator =: This should never be called."); +} + +void Node::insertEntry(uint32_t dataLength, byte* pData, Region& mbr, id_type id) +{ + assert(m_children < m_capacity); + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + m_totalDataLength += dataLength; + ++m_children; + + m_nodeMBR.combineRegion(mbr); +} + +void Node::deleteEntry(uint32_t index) +{ + assert(index >= 0 && index < m_children); + + // cache it, since I might need it for "touches" later. + RegionPtr ptrR = m_ptrMBR[index]; + + m_totalDataLength -= m_pDataLength[index]; + if (m_pData[index] != 0) delete[] m_pData[index]; + + if (m_children > 1 && index != m_children - 1) + { + m_pDataLength[index] = m_pDataLength[m_children - 1]; + m_pData[index] = m_pData[m_children - 1]; + m_ptrMBR[index] = m_ptrMBR[m_children - 1]; + m_pIdentifier[index] = m_pIdentifier[m_children - 1]; + } + + --m_children; + + // WARNING: index has now changed. Do not use it below here. + + if (m_children == 0) + { + m_nodeMBR = m_pTree->m_infiniteRegion; + } + else if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesRegion(*ptrR)) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[u32Child]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[u32Child]->m_pHigh[cDim]); + } + } + } +} + +bool Node::insertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + if (m_children < m_capacity) + { + bool adjusted = false; + + // this has to happen before insertEntry modifies m_nodeMBR. + bool b = m_nodeMBR.containsRegion(mbr); + + insertEntry(dataLength, pData, mbr, id); + m_pTree->writeNode(this); + + if ((! b) && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + adjusted = true; + } + + return adjusted; + } + else if (m_pTree->m_treeVariant == RV_RSTAR && (! pathBuffer.empty()) && overflowTable[m_level] == 0) + { + overflowTable[m_level] = 1; + + std::vector<uint32_t> vReinsert, vKeep; + reinsertData(dataLength, pData, mbr, id, vReinsert, vKeep); + + uint32_t lReinsert = static_cast<uint32_t>(vReinsert.size()); + uint32_t lKeep = static_cast<uint32_t>(vKeep.size()); + + byte** reinsertdata = 0; + RegionPtr* reinsertmbr = 0; + id_type* reinsertid = 0; + uint32_t* reinsertlen = 0; + byte** keepdata = 0; + RegionPtr* keepmbr = 0; + id_type* keepid = 0; + uint32_t* keeplen = 0; + + try + { + reinsertdata = new byte*[lReinsert]; + reinsertmbr = new RegionPtr[lReinsert]; + reinsertid = new id_type[lReinsert]; + reinsertlen = new uint32_t[lReinsert]; + + keepdata = new byte*[m_capacity + 1]; + keepmbr = new RegionPtr[m_capacity + 1]; + keepid = new id_type[m_capacity + 1]; + keeplen = new uint32_t[m_capacity + 1]; + } + catch (...) + { + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + delete[] keepdata; + delete[] keepmbr; + delete[] keepid; + delete[] keeplen; + throw; + } + + uint32_t cIndex; + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + reinsertlen[cIndex] = m_pDataLength[vReinsert[cIndex]]; + reinsertdata[cIndex] = m_pData[vReinsert[cIndex]]; + reinsertmbr[cIndex] = m_ptrMBR[vReinsert[cIndex]]; + reinsertid[cIndex] = m_pIdentifier[vReinsert[cIndex]]; + } + + for (cIndex = 0; cIndex < lKeep; ++cIndex) + { + keeplen[cIndex] = m_pDataLength[vKeep[cIndex]]; + keepdata[cIndex] = m_pData[vKeep[cIndex]]; + keepmbr[cIndex] = m_ptrMBR[vKeep[cIndex]]; + keepid[cIndex] = m_pIdentifier[vKeep[cIndex]]; + } + + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + + m_pDataLength = keeplen; + m_pData = keepdata; + m_ptrMBR = keepmbr; + m_pIdentifier = keepid; + m_children = lKeep; + m_totalDataLength = 0; + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) m_totalDataLength += m_pDataLength[u32Child]; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[u32Child]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[u32Child]->m_pHigh[cDim]); + } + } + + m_pTree->writeNode(this); + + // Divertion from R*-Tree algorithm here. First adjust + // the path to the root, then start reinserts, to avoid complicated handling + // of changes to the same node from multiple insertions. + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + m_pTree->insertData_impl( + reinsertlen[cIndex], reinsertdata[cIndex], + *(reinsertmbr[cIndex]), reinsertid[cIndex], + m_level, overflowTable); + } + + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + + return true; + } + else + { + NodePtr n; + NodePtr nn; + split(dataLength, pData, mbr, id, n, nn); + + if (pathBuffer.empty()) + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = -1; + nn->m_identifier = -1; + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + NodePtr ptrR = m_pTree->m_indexPool.acquire(); + if (ptrR.get() == 0) + { + ptrR = NodePtr(new Index(m_pTree, m_pTree->m_rootID, m_level + 1), &(m_pTree->m_indexPool)); + } + else + { + //ptrR->m_pTree = m_pTree; + ptrR->m_identifier = m_pTree->m_rootID; + ptrR->m_level = m_level + 1; + ptrR->m_nodeMBR = m_pTree->m_infiniteRegion; + } + + ptrR->insertEntry(0, 0, n->m_nodeMBR, n->m_identifier); + ptrR->insertEntry(0, 0, nn->m_nodeMBR, nn->m_identifier); + + m_pTree->writeNode(ptrR.get()); + + m_pTree->m_stats.m_nodesInLevel[m_level] = 2; + m_pTree->m_stats.m_nodesInLevel.push_back(1); + m_pTree->m_stats.m_u32TreeHeight = m_level + 2; + } + else + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = m_identifier; + nn->m_identifier = -1; + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(n.get(), nn.get(), pathBuffer, overflowTable); + } + + return true; + } +} + +void Node::reinsertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep) +{ + ReinsertEntry** v = new ReinsertEntry*[m_capacity + 1]; + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + PointPtr nc = m_pTree->m_pointPool.acquire(); + m_nodeMBR.getCenter(*nc); + PointPtr c = m_pTree->m_pointPool.acquire(); + + for (uint32_t u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + try + { + v[u32Child] = new ReinsertEntry(u32Child, 0.0); + } + catch (...) + { + for (uint32_t i = 0; i < u32Child; ++i) delete v[i]; + delete[] v; + throw; + } + + m_ptrMBR[u32Child]->getCenter(*c); + + // calculate relative distance of every entry from the node MBR (ignore square root.) + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + double d = nc->m_pCoords[cDim] - c->m_pCoords[cDim]; + v[u32Child]->m_dist += d * d; + } + } + + // sort by increasing order of distances. + ::qsort(v, m_capacity + 1, sizeof(ReinsertEntry*), ReinsertEntry::compareReinsertEntry); + + uint32_t cReinsert = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_reinsertFactor)); + + uint32_t cCount; + + for (cCount = 0; cCount < cReinsert; ++cCount) + { + reinsert.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + for (cCount = cReinsert; cCount < m_capacity + 1; ++cCount) + { + keep.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + delete[] v; +} + +void Node::rtreeSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + uint32_t u32Child; + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + // use this mask array for marking visited entries. + byte* mask = new byte[m_capacity + 1]; + bzero(mask, m_capacity + 1); + + // insert new data in the node for easier manipulation. Data arrays are always + // by one larger than node capacity. + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + // m_totalDataLength does not need to be increased here. + + // initialize each group with the seed entries. + uint32_t seed1, seed2; + pickSeeds(seed1, seed2); + + group1.push_back(seed1); + group2.push_back(seed2); + + mask[seed1] = 1; + mask[seed2] = 1; + + // find MBR of each group. + RegionPtr mbr1 = m_pTree->m_regionPool.acquire(); + *mbr1 = *(m_ptrMBR[seed1]); + RegionPtr mbr2 = m_pTree->m_regionPool.acquire(); + *mbr2 = *(m_ptrMBR[seed2]); + + // count how many entries are left unchecked (exclude the seeds here.) + uint32_t cRemaining = m_capacity + 1 - 2; + + while (cRemaining > 0) + { + if (minimumLoad - group1.size() == cRemaining) + { + // all remaining entries must be assigned to group1 to comply with minimun load requirement. + for (u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + if (mask[u32Child] == 0) + { + group1.push_back(u32Child); + mask[u32Child] = 1; + --cRemaining; + } + } + } + else if (minimumLoad - group2.size() == cRemaining) + { + // all remaining entries must be assigned to group2 to comply with minimun load requirement. + for (u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + if (mask[u32Child] == 0) + { + group2.push_back(u32Child); + mask[u32Child] = 1; + --cRemaining; + } + } + } + else + { + // For all remaining entries compute the difference of the cost of grouping an + // entry in either group. When done, choose the entry that yielded the maximum + // difference. In case of linear split, select any entry (e.g. the first one.) + uint32_t sel; + double md1 = 0.0, md2 = 0.0; + double m = -std::numeric_limits<double>::max(); + double d1, d2, d; + double a1 = mbr1->getArea(); + double a2 = mbr2->getArea(); + + RegionPtr a = m_pTree->m_regionPool.acquire(); + RegionPtr b = m_pTree->m_regionPool.acquire(); + + for (u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + if (mask[u32Child] == 0) + { + mbr1->getCombinedRegion(*a, *(m_ptrMBR[u32Child])); + d1 = a->getArea() - a1; + mbr2->getCombinedRegion(*b, *(m_ptrMBR[u32Child])); + d2 = b->getArea() - a2; + d = std::abs(d1 - d2); + + if (d > m) + { + m = d; + md1 = d1; md2 = d2; + sel = u32Child; + if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break; + } + } + } + + // determine the group where we should add the new entry. + int32_t group = -1; + + if (md1 < md2) + { + group1.push_back(sel); + group = 1; + } + else if (md2 < md1) + { + group2.push_back(sel); + group = 2; + } + else if (a1 < a2) + { + group1.push_back(sel); + group = 1; + } + else if (a2 < a1) + { + group2.push_back(sel); + group = 2; + } + else if (group1.size() < group2.size()) + { + group1.push_back(sel); + group = 1; + } + else if (group2.size() < group1.size()) + { + group2.push_back(sel); + group = 2; + } + else + { + group1.push_back(sel); + group = 1; + } + mask[sel] = 1; + --cRemaining; + if (group == 1) + { + mbr1->combineRegion(*(m_ptrMBR[sel])); + } + else + { + mbr2->combineRegion(*(m_ptrMBR[sel])); + } + } + } + + delete[] mask; +} + +void Node::rstarSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + RstarSplitEntry** dataLow = 0; + RstarSplitEntry** dataHigh = 0; + + try + { + dataLow = new RstarSplitEntry*[m_capacity + 1]; + dataHigh = new RstarSplitEntry*[m_capacity + 1]; + } + catch (...) + { + delete[] dataLow; + throw; + } + + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + // m_totalDataLength does not need to be increased here. + + uint32_t nodeSPF = static_cast<uint32_t>( + std::floor((m_capacity + 1) * m_pTree->m_splitDistributionFactor)); + uint32_t splitDistribution = (m_capacity + 1) - (2 * nodeSPF) + 2; + + uint32_t u32Child = 0, cDim, cIndex; + + for (u32Child = 0; u32Child <= m_capacity; ++u32Child) + { + try + { + dataLow[u32Child] = new RstarSplitEntry(m_ptrMBR[u32Child].get(), u32Child, 0); + } + catch (...) + { + for (uint32_t i = 0; i < u32Child; ++i) delete dataLow[i]; + delete[] dataLow; + delete[] dataHigh; + throw; + } + + dataHigh[u32Child] = dataLow[u32Child]; + } + + double minimumMargin = std::numeric_limits<double>::max(); + uint32_t splitAxis = std::numeric_limits<uint32_t>::max(); + uint32_t sortOrder = std::numeric_limits<uint32_t>::max(); + + // chooseSplitAxis. + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow); + ::qsort(dataHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh); + + // calculate sum of margins and overlap for all distributions. + double marginl = 0.0; + double marginh = 0.0; + + Region bbl1, bbl2, bbh1, bbh2; + + for (u32Child = 1; u32Child <= splitDistribution; ++u32Child) + { + uint32_t l = nodeSPF - 1 + u32Child; + + bbl1 = *(dataLow[0]->m_pRegion); + bbh1 = *(dataHigh[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bbl1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh1.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + bbl2 = *(dataLow[l]->m_pRegion); + bbh2 = *(dataHigh[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bbl2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh2.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + marginl += bbl1.getMargin() + bbl2.getMargin(); + marginh += bbh1.getMargin() + bbh2.getMargin(); + } // for (u32Child) + + double margin = std::min(marginl, marginh); + + // keep minimum margin as split axis. + if (margin < minimumMargin) + { + minimumMargin = margin; + splitAxis = cDim; + sortOrder = (marginl < marginh) ? 0 : 1; + } + + // increase the dimension according to which the data entries should be sorted. + for (u32Child = 0; u32Child <= m_capacity; ++u32Child) + { + dataLow[u32Child]->m_sortDim = cDim + 1; + } + } // for (cDim) + + for (u32Child = 0; u32Child <= m_capacity; ++u32Child) + { + dataLow[u32Child]->m_sortDim = splitAxis; + } + + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), (sortOrder == 0) ? RstarSplitEntry::compareLow : RstarSplitEntry::compareHigh); + + double ma = std::numeric_limits<double>::max(); + double mo = std::numeric_limits<double>::max(); + uint32_t splitPoint = std::numeric_limits<uint32_t>::max(); + + Region bb1, bb2; + + for (u32Child = 1; u32Child <= splitDistribution; ++u32Child) + { + uint32_t l = nodeSPF - 1 + u32Child; + + bb1 = *(dataLow[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bb1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + bb2 = *(dataLow[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bb2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + double o = bb1.getIntersectingArea(bb2); + + if (o < mo) + { + splitPoint = u32Child; + mo = o; + ma = bb1.getArea() + bb2.getArea(); + } + else if (o == mo) + { + double a = bb1.getArea() + bb2.getArea(); + + if (a < ma) + { + splitPoint = u32Child; + ma = a; + } + } + } // for (u32Child) + + uint32_t l1 = nodeSPF - 1 + splitPoint; + + for (cIndex = 0; cIndex < l1; ++cIndex) + { + group1.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + for (cIndex = l1; cIndex <= m_capacity; ++cIndex) + { + group2.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + delete[] dataLow; + delete[] dataHigh; +} + +void Node::pickSeeds(uint32_t& index1, uint32_t& index2) +{ + double separation = -std::numeric_limits<double>::max(); + double inefficiency = -std::numeric_limits<double>::max(); + uint32_t cDim, u32Child, cIndex; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_RSTAR: + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + double leastLower = m_ptrMBR[0]->m_pLow[cDim]; + double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim]; + uint32_t greatestLower = 0; + uint32_t leastUpper = 0; + double width; + + for (u32Child = 1; u32Child <= m_capacity; ++u32Child) + { + if (m_ptrMBR[u32Child]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = u32Child; + if (m_ptrMBR[u32Child]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = u32Child; + + leastLower = std::min(m_ptrMBR[u32Child]->m_pLow[cDim], leastLower); + greatestUpper = std::max(m_ptrMBR[u32Child]->m_pHigh[cDim], greatestUpper); + } + + width = greatestUpper - leastLower; + if (width <= 0) width = 1; + + double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width; + + if (f > separation) + { + index1 = leastUpper; + index2 = greatestLower; + separation = f; + } + } // for (cDim) + + if (index1 == index2) + { + if (index2 == 0) ++index2; + else --index2; + } + + break; + case RV_QUADRATIC: + // for each pair of Regions (account for overflow Region too!) + for (u32Child = 0; u32Child < m_capacity; ++u32Child) + { + double a = m_ptrMBR[u32Child]->getArea(); + + for (cIndex = u32Child + 1; cIndex <= m_capacity; ++cIndex) + { + // get the combined MBR of those two entries. + Region r; + m_ptrMBR[u32Child]->getCombinedRegion(r, *(m_ptrMBR[cIndex])); + + // find the inefficiency of grouping these entries together. + double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea(); + + if (d > inefficiency) + { + inefficiency = d; + index1 = u32Child; + index2 = cIndex; + } + } // for (cIndex) + } // for (u32Child) + + break; + default: + throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported."); + } +} + +void Node::condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis) +{ + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + if (pathBuffer.empty()) + { + // eliminate root if it has only one child. + if (m_level != 0 && m_children == 1) + { + NodePtr ptrN = m_pTree->readNode(m_pIdentifier[0]); + m_pTree->deleteNode(ptrN.get()); + ptrN->m_identifier = m_pTree->m_rootID; + m_pTree->writeNode(ptrN.get()); + + m_pTree->m_stats.m_nodesInLevel.pop_back(); + m_pTree->m_stats.m_u32TreeHeight -= 1; + // HACK: pending deleteNode for deleted child will decrease nodesInLevel, later on. + m_pTree->m_stats.m_nodesInLevel[m_pTree->m_stats.m_u32TreeHeight - 1] = 2; + } + } + else + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrParent = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrParent.get()); + + // find the entry in the parent, that points to this node. + uint32_t child; + + for (child = 0; child != p->m_children; ++child) + { + if (p->m_pIdentifier[child] == m_identifier) break; + } + + if (m_children < minimumLoad) + { + // used space less than the minimum + // 1. eliminate node entry from the parent. deleteEntry will fix the parent's MBR. + p->deleteEntry(child); + // 2. add this node to the stack in order to reinsert its entries. + toReinsert.push(ptrThis); + } + else + { + // adjust the entry in 'p' to contain the new bounding region of this node. + *(p->m_ptrMBR[child]) = m_nodeMBR; + + // global recalculation necessary since the MBR can only shrink in size, + // due to data removal. + if (m_pTree->m_bTightMBRs) + { + for (uint32_t cDim = 0; cDim < p->m_nodeMBR.m_dimension; ++cDim) + { + p->m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t u32Child = 0; u32Child < p->m_children; ++u32Child) + { + p->m_nodeMBR.m_pLow[cDim] = std::min(p->m_nodeMBR.m_pLow[cDim], p->m_ptrMBR[u32Child]->m_pLow[cDim]); + p->m_nodeMBR.m_pHigh[cDim] = std::max(p->m_nodeMBR.m_pHigh[cDim], p->m_ptrMBR[u32Child]->m_pHigh[cDim]); + } + } + } + } + + // write parent node back to storage. + m_pTree->writeNode(p); + + p->condenseTree(toReinsert, pathBuffer, ptrParent); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Node.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Node.h.svn-base new file mode 100644 index 000000000..89e55945d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Node.h.svn-base @@ -0,0 +1,188 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class RTree; + class Leaf; + class Index; + class Node; + + typedef Tools::PoolPointer<Node> NodePtr; + + class Node : public SpatialIndex::INode + { + public: + virtual ~Node(); + + // + // Tools::IObject interface + // + virtual Tools::IObject* clone(); + + // + // Tools::ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // SpatialIndex::IEntry interface + // + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + + // + // SpatialIndex::INode interface + // + virtual uint32_t getChildrenCount() const; + virtual id_type getChildIdentifier(uint32_t index) const; + virtual void getChildShape(uint32_t index, IShape** out) const; + virtual void getChildData(uint32_t index, uint32_t& length, byte** data) const; + virtual uint32_t getLevel() const; + virtual bool isIndex() const; + virtual bool isLeaf() const; + + private: + Node(); + Node(RTree* pTree, id_type id, uint32_t level, uint32_t capacity); + + virtual Node& operator=(const Node&); + + virtual void insertEntry(uint32_t dataLength, byte* pData, Region& mbr, id_type id); + virtual void deleteEntry(uint32_t index); + + virtual bool insertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable); + virtual void reinsertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep); + + virtual void rtreeSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2); + virtual void rstarSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2); + + virtual void pickSeeds(uint32_t& index1, uint32_t& index2); + + virtual void condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis); + + virtual NodePtr chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer) = 0; + + virtual void split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& left, NodePtr& right) = 0; + + RTree* m_pTree; + // Parent of all nodes. + + uint32_t m_level; + // The level of the node in the tree. + // Leaves are always at level 0. + + id_type m_identifier; + // The unique ID of this node. + + uint32_t m_children; + // The number of children pointed by this node. + + uint32_t m_capacity; + // Specifies the node capacity. + + Region m_nodeMBR; + // The minimum bounding region enclosing all data contained in the node. + + byte** m_pData; + // The data stored in the node. + + RegionPtr* m_ptrMBR; + // The corresponding data MBRs. + + id_type* m_pIdentifier; + // The corresponding data identifiers. + + uint32_t* m_pDataLength; + + uint32_t m_totalDataLength; + + class RstarSplitEntry + { + public: + Region* m_pRegion; + uint32_t m_index; + uint32_t m_sortDim; + + RstarSplitEntry(Region* pr, uint32_t index, uint32_t dimension) : + m_pRegion(pr), m_index(index), m_sortDim(dimension) {} + + static int compareLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + assert(pe1->m_sortDim == pe2->m_sortDim); + + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] < pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] > pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return 1; + return 0; + } + + static int compareHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + assert(pe1->m_sortDim == pe2->m_sortDim); + + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return 1; + return 0; + } + }; // RstarSplitEntry + + class ReinsertEntry + { + public: + uint32_t m_index; + double m_dist; + + ReinsertEntry(uint32_t index, double dist) : m_index(index), m_dist(dist) {} + + static int compareReinsertEntry(const void* pv1, const void* pv2) + { + ReinsertEntry* pe1 = * (ReinsertEntry**) pv1; + ReinsertEntry* pe2 = * (ReinsertEntry**) pv2; + + if (pe1->m_dist < pe2->m_dist) return -1; + if (pe1->m_dist > pe2->m_dist) return 1; + return 0; + } + }; // ReinsertEntry + + // Needed to access protected members without having to cast from Node. + // It is more efficient than using member functions to access protected members. + friend class RTree; + friend class Leaf; + friend class Index; + friend class Tools::PointerPool<Node>; + friend class BulkLoader; + }; // Node + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/PointerPoolNode.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/PointerPoolNode.h.svn-base new file mode 100644 index 000000000..e6977a0c9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/PointerPoolNode.h.svn-base @@ -0,0 +1,138 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#ifndef __spatialindex_rtree_pointer_pool_node_h +#define __spatialindex_rtree_pointer_pool_node_h + +#include "Node.h" + +namespace Tools +{ + template<> class PointerPool<RTree::Node> + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + RTree::Node* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<RTree::Node> acquire() + { + if (! m_pool.empty()) + { + RTree::Node* p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + ++m_hits; + #endif + + return PoolPointer<RTree::Node>(p, this); + } + #ifndef NDEBUG + else + { + // fixme: well sort of... + ++m_pointerCount; + ++m_misses; + } + #endif + + return PoolPointer<RTree::Node>(); + } + + void release(RTree::Node* p) + { + if (p != 0) + { + if (m_pool.size() < m_capacity) + { + if (p->m_pData != 0) + { + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + // there is no need to set the pointer to zero, after deleting it, + // since it will be redeleted only if it is actually initialized again, + // a fact that will be depicted by variable m_children. + if (p->m_pData[cChild] != 0) delete[] p->m_pData[cChild]; + } + } + + p->m_level = 0; + p->m_identifier = -1; + p->m_children = 0; + p->m_totalDataLength = 0; + + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + protected: + uint32_t m_capacity; + std::stack<RTree::Node*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + +#endif /* __spatialindex_rtree_pointer_pool_node_h */ diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/RTree.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/RTree.cc.svn-base new file mode 100644 index 000000000..dd5f23c45 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/RTree.cc.svn-base @@ -0,0 +1,1551 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" +#include "BulkLoader.h" +#include "RTree.h" + +using namespace SpatialIndex::RTree; + +SpatialIndex::RTree::Data::Data(uint32_t len, byte* pData, Region& r, id_type id) + : m_id(id), m_region(r), m_pData(0), m_dataLength(len) +{ + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, pData, m_dataLength); + } +} + +SpatialIndex::RTree::Data::~Data() +{ + delete[] m_pData; +} + +SpatialIndex::RTree::Data* SpatialIndex::RTree::Data::clone() +{ + return new Data(m_dataLength, m_pData, m_region, m_id); +} + +id_type SpatialIndex::RTree::Data::getIdentifier() const +{ + return m_id; +} + +void SpatialIndex::RTree::Data::getShape(IShape** out) const +{ + *out = new Region(m_region); +} + +void SpatialIndex::RTree::Data::getData(uint32_t& len, byte** data) const +{ + len = m_dataLength; + *data = 0; + + if (m_dataLength > 0) + { + *data = new byte[m_dataLength]; + memcpy(*data, m_pData, m_dataLength); + } +} + +uint32_t SpatialIndex::RTree::Data::getByteArraySize() +{ + return + sizeof(id_type) + + sizeof(uint32_t) + + m_dataLength + + m_region.getByteArraySize(); +} + +void SpatialIndex::RTree::Data::loadFromByteArray(const byte* ptr) +{ + memcpy(&m_id, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + delete[] m_pData; + m_pData = 0; + + memcpy(&m_dataLength, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, ptr, m_dataLength); + ptr += m_dataLength; + } + + m_region.loadFromByteArray(ptr); +} + +void SpatialIndex::RTree::Data::storeToByteArray(byte** data, uint32_t& len) +{ + // it is thread safe this way. + uint32_t regionsize; + byte* regiondata = 0; + m_region.storeToByteArray(®iondata, regionsize); + + len = sizeof(id_type) + sizeof(uint32_t) + m_dataLength + regionsize; + + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_id, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_dataLength, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + memcpy(ptr, m_pData, m_dataLength); + ptr += m_dataLength; + } + + memcpy(ptr, regiondata, regionsize); + delete[] regiondata; + // ptr += regionsize; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::returnRTree(SpatialIndex::IStorageManager& sm, Tools::PropertySet& ps) +{ + SpatialIndex::ISpatialIndex* si = new SpatialIndex::RTree::RTree(sm, ps); + return si; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::createNewRTree( + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + RTreeVariant rv, + id_type& indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = fillFactor; + ps.setProperty("FillFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = indexCapacity; + ps.setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = leafCapacity; + ps.setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = dimension; + ps.setProperty("Dimension", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = rv; + ps.setProperty("TreeVariant", var); + + ISpatialIndex* ret = returnRTree(sm, ps); + + var.m_varType = Tools::VT_LONGLONG; + var = ps.getProperty("IndexIdentifier"); + indexIdentifier = var.m_val.llVal; + + return ret; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + SpatialIndex::RTree::RTreeVariant rv, + id_type& indexIdentifier) +{ + SpatialIndex::ISpatialIndex* tree = createNewRTree(sm, fillFactor, indexCapacity, leafCapacity, dimension, rv, indexIdentifier); + + uint32_t bindex = static_cast<uint32_t>(std::floor(static_cast<double>(indexCapacity * fillFactor))); + uint32_t bleaf = static_cast<uint32_t>(std::floor(static_cast<double>(leafCapacity * fillFactor))); + + SpatialIndex::RTree::BulkLoader bl; + + switch (m) + { + case BLM_STR: + bl.bulkLoadUsingSTR(static_cast<RTree*>(tree), stream, bindex, bleaf, 10000, 100); + break; + default: + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Unknown bulk load method."); + break; + } + + return tree; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + SpatialIndex::IStorageManager& sm, + Tools::PropertySet& ps, + id_type& indexIdentifier) +{ + Tools::Variant var; + RTreeVariant rv; + double fillFactor; + uint32_t indexCapacity, leafCapacity, dimension, pageSize, numberOfPages; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != RV_LINEAR && + var.m_val.lVal != RV_QUADRATIC && + var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property TreeVariant must be Tools::VT_LONG and of RTreeVariant type"); + + rv = static_cast<RTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property FillFactor was not of type Tools::VT_DOUBLE"); + + if (var.m_val.dblVal <= 0.0) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property FillFactor was less than 0.0"); + + if (((rv == RV_LINEAR || rv == RV_QUADRATIC) && var.m_val.dblVal > 0.5)) + throw Tools::IllegalArgumentException( "createAndBulkLoadNewRTree: Property FillFactor must be in range (0.0, 0.5) for LINEAR or QUADRATIC index types"); + if ( var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property FillFactor must be in range (0.0, 1.0) for RSTAR index type"); + fillFactor = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property IndexCapacity must be Tools::VT_ULONG and >= 4"); + + indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property LeafCapacity must be Tools::VT_ULONG and >= 4"); + + leafCapacity = var.m_val.ulVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property Dimension must be greater than 1"); + + dimension = var.m_val.ulVal; + } + + // page size + var = ps.getProperty("ExternalSortBufferPageSize"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferPageSize must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferPageSize must be greater than 1"); + + pageSize = var.m_val.ulVal; + } + + // number of pages + var = ps.getProperty("ExternalSortBufferTotalPages"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferTotalPages must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferTotalPages must be greater than 1"); + + numberOfPages = var.m_val.ulVal; + } + + SpatialIndex::ISpatialIndex* tree = createNewRTree(sm, fillFactor, indexCapacity, leafCapacity, dimension, rv, indexIdentifier); + + uint32_t bindex = static_cast<uint32_t>(std::floor(static_cast<double>(indexCapacity * fillFactor))); + uint32_t bleaf = static_cast<uint32_t>(std::floor(static_cast<double>(leafCapacity * fillFactor))); + + SpatialIndex::RTree::BulkLoader bl; + + switch (m) + { + case BLM_STR: + bl.bulkLoadUsingSTR(static_cast<RTree*>(tree), stream, bindex, bleaf, pageSize, numberOfPages); + break; + default: + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Unknown bulk load method."); + break; + } + + return tree; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::loadRTree(IStorageManager& sm, id_type indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = indexIdentifier; + ps.setProperty("IndexIdentifier", var); + + return returnRTree(sm, ps); +} + +SpatialIndex::RTree::RTree::RTree(IStorageManager& sm, Tools::PropertySet& ps) : + m_pStorageManager(&sm), + m_rootID(StorageManager::NewPage), + m_headerID(StorageManager::NewPage), + m_treeVariant(RV_RSTAR), + m_fillFactor(0.7), + m_indexCapacity(100), + m_leafCapacity(100), + m_nearMinimumOverlapFactor(32), + m_splitDistributionFactor(0.4), + m_reinsertFactor(0.3), + m_dimension(2), + m_bTightMBRs(true), + m_pointPool(500), + m_regionPool(1000), + m_indexPool(100), + m_leafPool(100) +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + + Tools::Variant var = ps.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType == Tools::VT_LONGLONG) m_headerID = var.m_val.llVal; + else if (var.m_varType == Tools::VT_LONG) m_headerID = var.m_val.lVal; + // for backward compatibility only. + else throw Tools::IllegalArgumentException("RTree: Property IndexIdentifier must be Tools::VT_LONGLONG"); + + initOld(ps); + } + else + { + initNew(ps); + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = m_headerID; + ps.setProperty("IndexIdentifier", var); + } +} + +SpatialIndex::RTree::RTree::~RTree() +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_destroy(&m_rwLock); +#endif + + storeHeader(); +} + +// +// ISpatialIndex interface +// + +void SpatialIndex::RTree::RTree::insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("insertData: cannot acquire an exclusive lock"); +#endif + + try + { + // convert the shape into a Region (R-Trees index regions only; i.e., approximations of the shapes). + RegionPtr mbr = m_regionPool.acquire(); + shape.getMBR(*mbr); + + byte* buffer = 0; + + if (len > 0) + { + buffer = new byte[len]; + memcpy(buffer, pData, len); + } + + insertData_impl(len, buffer, *mbr, id); + // the buffer is stored in the tree. Do not delete here. + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +bool SpatialIndex::RTree::RTree::deleteData(const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("deleteData: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("deleteData: cannot acquire an exclusive lock"); +#endif + + try + { + RegionPtr mbr = m_regionPool.acquire(); + shape.getMBR(*mbr); + bool ret = deleteData_impl(*mbr, id); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + return ret; + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::containsWhatQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("containsWhatQuery: Shape has the wrong number of dimensions."); + rangeQuery(ContainmentQuery, query, v); +} + +void SpatialIndex::RTree::RTree::intersectsWithQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("intersectsWithQuery: Shape has the wrong number of dimensions."); + rangeQuery(IntersectionQuery, query, v); +} + +void SpatialIndex::RTree::RTree::pointLocationQuery(const Point& query, IVisitor& v) +{ + if (query.m_dimension != m_dimension) throw Tools::IllegalArgumentException("pointLocationQuery: Shape has the wrong number of dimensions."); + Region r(query, query); + rangeQuery(IntersectionQuery, r, v); +} + +void SpatialIndex::RTree::RTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("nearestNeighborQuery: cannot acquire a shared lock"); +#endif + + try + { + std::priority_queue<NNEntry*, std::vector<NNEntry*>, NNEntry::ascending> queue; + + queue.push(new NNEntry(m_rootID, 0, 0.0)); + + uint32_t count = 0; + double knearest = 0.0; + + while (! queue.empty()) + { + NNEntry* pFirst = queue.top(); + + // report all nearest neighbors with equal greatest distances. + // (neighbors can be more than k, if many happen to have the same greatest distance). + if (count >= k && pFirst->m_minDist > knearest) break; + + queue.pop(); + + if (pFirst->m_pEntry == 0) + { + // n is a leaf or an index. + NodePtr n = readNode(pFirst->m_id); + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (n->m_level == 0) + { + Data* e = new Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + // we need to compare the query with the actual data entry here, so we call the + // appropriate getMinimumDistance method of NearestNeighborComparator. + queue.push(new NNEntry(n->m_pIdentifier[cChild], e, nnc.getMinimumDistance(query, *e))); + } + else + { + queue.push(new NNEntry(n->m_pIdentifier[cChild], 0, nnc.getMinimumDistance(query, *(n->m_ptrMBR[cChild])))); + } + } + } + else + { + v.visitData(*(static_cast<IData*>(pFirst->m_pEntry))); + ++(m_stats.m_u64QueryResults); + ++count; + knearest = pFirst->m_minDist; + delete pFirst->m_pEntry; + } + + delete pFirst; + } + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + if (e->m_pEntry != 0) delete e->m_pEntry; + delete e; + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + NNComparator nnc; + nearestNeighborQuery(k, query, v, nnc); +} + + +void SpatialIndex::RTree::RTree::selfJoinQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) + throw Tools::IllegalArgumentException("selfJoinQuery: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("selfJoinQuery: cannot acquire a shared lock"); +#endif + + try + { + RegionPtr mbr = m_regionPool.acquire(); + query.getMBR(*mbr); + selfJoinQuery(m_rootID, m_rootID, *mbr, v); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::queryStrategy(IQueryStrategy& qs) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("queryStrategy: cannot acquire a shared lock"); +#endif + + id_type next = m_rootID; + bool hasNext = true; + + try + { + while (hasNext) + { + NodePtr n = readNode(next); + qs.getNextEntry(*n, next, hasNext); + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::getIndexProperties(Tools::PropertySet& out) const +{ + Tools::Variant var; + + // dimension + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_dimension; + out.setProperty("Dimension", var); + + // index capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexCapacity; + out.setProperty("IndexCapacity", var); + + // leaf capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafCapacity; + out.setProperty("LeafCapacity", var); + + // R-tree variant + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = m_treeVariant; + out.setProperty("TreeVariant", var); + + // fill factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_fillFactor; + out.setProperty("FillFactor", var); + + // near minimum overlap factor + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_nearMinimumOverlapFactor; + out.setProperty("NearMinimumOverlapFactor", var); + + // split distribution factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_splitDistributionFactor; + out.setProperty("SplitDistributionFactor", var); + + // reinsert factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_reinsertFactor; + out.setProperty("ReinsertFactor", var); + + // tight MBRs + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = m_bTightMBRs; + out.setProperty("EnsureTightMBRs", var); + + // index pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexPool.getCapacity(); + out.setProperty("IndexPoolCapacity", var); + + // leaf pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafPool.getCapacity(); + out.setProperty("LeafPoolCapacity", var); + + // region pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_regionPool.getCapacity(); + out.setProperty("RegionPoolCapacity", var); + + // point pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_pointPool.getCapacity(); + out.setProperty("PointPoolCapacity", var); +} + +void SpatialIndex::RTree::RTree::addCommand(ICommand* pCommand, CommandType ct) +{ + switch (ct) + { + case CT_NODEREAD: + m_readNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEWRITE: + m_writeNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEDELETE: + m_deleteNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + } +} + +bool SpatialIndex::RTree::RTree::isIndexValid() +{ + bool ret = true; + std::stack<ValidateEntry> st; + NodePtr root = readNode(m_rootID); + + if (root->m_level != m_stats.m_u32TreeHeight - 1) + { + std::cerr << "Invalid tree height." << std::endl; + return false; + } + + std::map<uint32_t, uint32_t> nodesInLevel; + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(root->m_level, 1)); + + ValidateEntry e(root->m_nodeMBR, root); + st.push(e); + + while (! st.empty()) + { + e = st.top(); st.pop(); + + Region tmpRegion; + tmpRegion = m_infiniteRegion; + + for (uint32_t cDim = 0; cDim < tmpRegion.m_dimension; ++cDim) + { + tmpRegion.m_pLow[cDim] = std::numeric_limits<double>::max(); + tmpRegion.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + tmpRegion.m_pLow[cDim] = std::min(tmpRegion.m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pLow[cDim]); + tmpRegion.m_pHigh[cDim] = std::max(tmpRegion.m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + + if (! (tmpRegion == e.m_pNode->m_nodeMBR)) + { + std::cerr << "Invalid parent information." << std::endl; + ret = false; + } + else if (! (tmpRegion == e.m_parentMBR)) + { + std::cerr << "Error in parent." << std::endl; + ret = false; + } + + if (e.m_pNode->m_level != 0) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]); + ValidateEntry tmpEntry(*(e.m_pNode->m_ptrMBR[cChild]), ptrN); + + std::map<uint32_t, uint32_t>::iterator itNodes = nodesInLevel.find(tmpEntry.m_pNode->m_level); + + if (itNodes == nodesInLevel.end()) + { + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(tmpEntry.m_pNode->m_level, 1l)); + } + else + { + nodesInLevel[tmpEntry.m_pNode->m_level] = nodesInLevel[tmpEntry.m_pNode->m_level] + 1; + } + + st.push(tmpEntry); + } + } + } + + uint32_t nodes = 0; + for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel) + { + if (nodesInLevel[cLevel] != m_stats.m_nodesInLevel[cLevel]) + { + std::cerr << "Invalid nodesInLevel information." << std::endl; + ret = false; + } + + nodes += m_stats.m_nodesInLevel[cLevel]; + } + + if (nodes != m_stats.m_u32Nodes) + { + std::cerr << "Invalid number of nodes information." << std::endl; + ret = false; + } + + return ret; +} + +void SpatialIndex::RTree::RTree::getStatistics(IStatistics** out) const +{ + *out = new Statistics(m_stats); +} + +void SpatialIndex::RTree::RTree::initNew(Tools::PropertySet& ps) +{ + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != RV_LINEAR && + var.m_val.lVal != RV_QUADRATIC && + var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initNew: Property TreeVariant must be Tools::VT_LONG and of RTreeVariant type"); + + m_treeVariant = static_cast<RTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) + throw Tools::IllegalArgumentException("initNew: Property FillFactor was not of type Tools::VT_DOUBLE"); + + if (var.m_val.dblVal <= 0.0) + throw Tools::IllegalArgumentException("initNew: Property FillFactor was less than 0.0"); + + if (((m_treeVariant == RV_LINEAR || m_treeVariant == RV_QUADRATIC) && var.m_val.dblVal > 0.5)) + throw Tools::IllegalArgumentException( "initNew: Property FillFactor must be in range " + "(0.0, 0.5) for LINEAR or QUADRATIC index types"); + if ( var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException( "initNew: Property FillFactor must be in range " + "(0.0, 1.0) for RSTAR index type"); + m_fillFactor = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property IndexCapacity must be Tools::VT_ULONG and >= 4"); + + m_indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property LeafCapacity must be Tools::VT_ULONG and >= 4"); + + m_leafCapacity = var.m_val.ulVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be greater than 1"); + + m_dimension = var.m_val.ulVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) + throw Tools::IllegalArgumentException("initNew: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); + + m_stats.m_u32TreeHeight = 1; + m_stats.m_nodesInLevel.push_back(0); + + Leaf root(this, -1); + m_rootID = writeNode(&root); + + storeHeader(); +} + +void SpatialIndex::RTree::RTree::initOld(Tools::PropertySet& ps) +{ + loadHeader(); + + // only some of the properties may be changed. + // the rest are just ignored. + + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != RV_LINEAR && + var.m_val.lVal != RV_QUADRATIC && + var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initOld: Property TreeVariant must be Tools::VT_LONG and of RTreeVariant type"); + + m_treeVariant = static_cast<RTreeVariant>(var.m_val.lVal); + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initOld: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); +} + +void SpatialIndex::RTree::RTree::storeHeader() +{ + const uint32_t headerSize = + sizeof(id_type) + // m_rootID + sizeof(RTreeVariant) + // m_treeVariant + sizeof(double) + // m_fillFactor + sizeof(uint32_t) + // m_indexCapacity + sizeof(uint32_t) + // m_leafCapacity + sizeof(uint32_t) + // m_nearMinimumOverlapFactor + sizeof(double) + // m_splitDistributionFactor + sizeof(double) + // m_reinsertFactor + sizeof(uint32_t) + // m_dimension + sizeof(char) + // m_bTightMBRs + sizeof(uint32_t) + // m_stats.m_nodes + sizeof(uint64_t) + // m_stats.m_data + sizeof(uint32_t) + // m_stats.m_treeHeight + m_stats.m_u32TreeHeight * sizeof(uint32_t); // m_stats.m_nodesInLevel + + byte* header = new byte[headerSize]; + byte* ptr = header; + + memcpy(ptr, &m_rootID, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_treeVariant, sizeof(RTreeVariant)); + ptr += sizeof(RTreeVariant); + memcpy(ptr, &m_fillFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_indexCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_leafCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_nearMinimumOverlapFactor, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_splitDistributionFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_reinsertFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c = (char) m_bTightMBRs; + memcpy(ptr, &c, sizeof(char)); + ptr += sizeof(char); + memcpy(ptr, &(m_stats.m_u32Nodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u64Data), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(ptr, &(m_stats.m_u32TreeHeight), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel) + { + memcpy(ptr, &(m_stats.m_nodesInLevel[cLevel]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + m_pStorageManager->storeByteArray(m_headerID, headerSize, header); + + delete[] header; +} + +void SpatialIndex::RTree::RTree::loadHeader() +{ + uint32_t headerSize; + byte* header = 0; + m_pStorageManager->loadByteArray(m_headerID, headerSize, &header); + + byte* ptr = header; + + memcpy(&m_rootID, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&m_treeVariant, ptr, sizeof(RTreeVariant)); + ptr += sizeof(RTreeVariant); + memcpy(&m_fillFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_indexCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_leafCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_nearMinimumOverlapFactor, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_splitDistributionFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_reinsertFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c; + memcpy(&c, ptr, sizeof(char)); + m_bTightMBRs = (c != 0); + ptr += sizeof(char); + memcpy(&(m_stats.m_u32Nodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u64Data), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(&(m_stats.m_u32TreeHeight), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel) + { + uint32_t cNodes; + memcpy(&cNodes, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + m_stats.m_nodesInLevel.push_back(cNodes); + } + + delete[] header; +} + +void SpatialIndex::RTree::RTree::insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id) +{ + assert(mbr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + byte* overflowTable = 0; + + try + { + NodePtr root = readNode(m_rootID); + + overflowTable = new byte[root->m_level]; + bzero(overflowTable, root->m_level); + + NodePtr l = root->chooseSubtree(mbr, 0, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mbr, id, pathBuffer, overflowTable); + + delete[] overflowTable; + ++(m_stats.m_u64Data); + } + catch (...) + { + delete[] overflowTable; + throw; + } +} + +void SpatialIndex::RTree::RTree::insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id, uint32_t level, byte* overflowTable) +{ + assert(mbr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_rootID); + NodePtr n = root->chooseSubtree(mbr, level, pathBuffer); + + assert(n->m_level == level); + + if (n.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + n->insertData(dataLength, pData, mbr, id, pathBuffer, overflowTable); +} + +bool SpatialIndex::RTree::RTree::deleteData_impl(const Region& mbr, id_type id) +{ + assert(mbr.m_dimension == m_dimension); + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_rootID); + NodePtr l = root->findLeaf(mbr, id, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + + if (l.get() != 0) + { + Leaf* pL = static_cast<Leaf*>(l.get()); + pL->deleteData(id, pathBuffer); + --(m_stats.m_u64Data); + return true; + } + + return false; +} + +SpatialIndex::id_type SpatialIndex::RTree::RTree::writeNode(Node* n) +{ + byte* buffer; + uint32_t dataLength; + n->storeToByteArray(&buffer, dataLength); + + id_type page; + if (n->m_identifier < 0) page = StorageManager::NewPage; + else page = n->m_identifier; + + try + { + m_pStorageManager->storeByteArray(page, dataLength, buffer); + delete[] buffer; + } + catch (InvalidPageException& e) + { + delete[] buffer; + std::cerr << e.what() << std::endl; + throw; + } + + if (n->m_identifier < 0) + { + n->m_identifier = page; + ++(m_stats.m_u32Nodes); + +#ifndef NDEBUG + try + { + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel.at(n->m_level) + 1; + } + catch(...) + { + throw Tools::IllegalStateException("writeNode: writing past the end of m_nodesInLevel."); + } +#else + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] + 1; +#endif + } + + ++(m_stats.m_u64Writes); + + for (size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex) + { + m_writeNodeCommands[cIndex]->execute(*n); + } + + return page; +} + +SpatialIndex::RTree::NodePtr SpatialIndex::RTree::RTree::readNode(id_type page) +{ + uint32_t dataLength; + byte* buffer; + + try + { + m_pStorageManager->loadByteArray(page, dataLength, &buffer); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + throw; + } + + try + { + uint32_t nodeType; + memcpy(&nodeType, buffer, sizeof(uint32_t)); + + NodePtr n; + + if (nodeType == PersistentIndex) n = m_indexPool.acquire(); + else if (nodeType == PersistentLeaf) n = m_leafPool.acquire(); + else throw Tools::IllegalStateException("readNode: failed reading the correct node type information"); + + if (n.get() == 0) + { + if (nodeType == PersistentIndex) n = NodePtr(new Index(this, -1, 0), &m_indexPool); + else if (nodeType == PersistentLeaf) n = NodePtr(new Leaf(this, -1), &m_leafPool); + } + + //n->m_pTree = this; + n->m_identifier = page; + n->loadFromByteArray(buffer); + + ++(m_stats.m_u64Reads); + + for (size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex) + { + m_readNodeCommands[cIndex]->execute(*n); + } + + delete[] buffer; + return n; + } + catch (...) + { + delete[] buffer; + throw; + } +} + +void SpatialIndex::RTree::RTree::deleteNode(Node* n) +{ + try + { + m_pStorageManager->deleteByteArray(n->m_identifier); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + throw; + } + + --(m_stats.m_u32Nodes); + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] - 1; + + for (size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex) + { + m_deleteNodeCommands[cIndex]->execute(*n); + } +} + +void SpatialIndex::RTree::RTree::rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("rangeQuery: cannot acquire a shared lock"); +#endif + + try + { + std::stack<NodePtr> st; + NodePtr root = readNode(m_rootID); + + if (root->m_children > 0 && query.intersectsShape(root->m_nodeMBR)) st.push(root); + + while (! st.empty()) + { + NodePtr n = st.top(); st.pop(); + + if (n->m_level == 0) + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + bool b; + if (type == ContainmentQuery) b = query.containsShape(*(n->m_ptrMBR[cChild])); + else b = query.intersectsShape(*(n->m_ptrMBR[cChild])); + + if (b) + { + Data data = Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + v.visitData(data); + ++(m_stats.m_u64QueryResults); + } + } + } + else + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (query.intersectsShape(*(n->m_ptrMBR[cChild]))) st.push(readNode(n->m_pIdentifier[cChild])); + } + } + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::selfJoinQuery(id_type id1, id_type id2, const Region& r, IVisitor& vis) +{ + NodePtr n1 = readNode(id1); + NodePtr n2 = readNode(id2); + vis.visitNode(*n1); + vis.visitNode(*n2); + + for (uint32_t cChild1 = 0; cChild1 < n1->m_children; ++cChild1) + { + if (r.intersectsRegion(*(n1->m_ptrMBR[cChild1]))) + { + for (uint32_t cChild2 = 0; cChild2 < n2->m_children; ++cChild2) + { + if ( + r.intersectsRegion(*(n2->m_ptrMBR[cChild2])) && + n1->m_ptrMBR[cChild1]->intersectsRegion(*(n2->m_ptrMBR[cChild2]))) + { + if (n1->m_level == 0) + { + if (n1->m_pIdentifier[cChild1] != n2->m_pIdentifier[cChild2]) + { + assert(n2->m_level == 0); + + std::vector<const IData*> v; + Data e1(n1->m_pDataLength[cChild1], n1->m_pData[cChild1], *(n1->m_ptrMBR[cChild1]), n1->m_pIdentifier[cChild1]); + Data e2(n2->m_pDataLength[cChild2], n2->m_pData[cChild2], *(n2->m_ptrMBR[cChild2]), n2->m_pIdentifier[cChild2]); + v.push_back(&e1); + v.push_back(&e2); + vis.visitData(v); + } + } + else + { + Region rr = r.getIntersectingRegion(n1->m_ptrMBR[cChild1]->getIntersectingRegion(*(n2->m_ptrMBR[cChild2]))); + selfJoinQuery(n1->m_pIdentifier[cChild1], n2->m_pIdentifier[cChild2], rr, vis); + } + } + } + } + } +} + +std::ostream& SpatialIndex::RTree::operator<<(std::ostream& os, const RTree& t) +{ + os << "Dimension: " << t.m_dimension << std::endl + << "Fill factor: " << t.m_fillFactor << std::endl + << "Index capacity: " << t.m_indexCapacity << std::endl + << "Leaf capacity: " << t.m_leafCapacity << std::endl + << "Tight MBRs: " << ((t.m_bTightMBRs) ? "enabled" : "disabled") << std::endl; + + if (t.m_treeVariant == RV_RSTAR) + { + os << "Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl + << "Reinsert factor: " << t.m_reinsertFactor << std::endl + << "Split distribution factor: " << t.m_splitDistributionFactor << std::endl; + } + + if (t.m_stats.getNumberOfNodesInLevel(0) > 0) + os << "Utilization: " << 100 * t.m_stats.getNumberOfData() / (t.m_stats.getNumberOfNodesInLevel(0) * t.m_leafCapacity) << "%" << std::endl + << t.m_stats; + + #ifndef NDEBUG + os << "Leaf pool hits: " << t.m_leafPool.m_hits << std::endl + << "Leaf pool misses: " << t.m_leafPool.m_misses << std::endl + << "Index pool hits: " << t.m_indexPool.m_hits << std::endl + << "Index pool misses: " << t.m_indexPool.m_misses << std::endl + << "Region pool hits: " << t.m_regionPool.m_hits << std::endl + << "Region pool misses: " << t.m_regionPool.m_misses << std::endl + << "Point pool hits: " << t.m_pointPool.m_hits << std::endl + << "Point pool misses: " << t.m_pointPool.m_misses << std::endl; + #endif + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/RTree.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/RTree.h.svn-base new file mode 100644 index 000000000..cb4e00452 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/RTree.h.svn-base @@ -0,0 +1,201 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Statistics.h" +#include "Node.h" +#include "PointerPoolNode.h" + +namespace SpatialIndex +{ + namespace RTree + { + class RTree : public ISpatialIndex + { + //class NNEntry; + + public: + RTree(IStorageManager&, Tools::PropertySet&); + // String Value Description + // ---------------------------------------------- + // IndexIndentifier VT_LONG If specified an existing index will be openened from the supplied + // storage manager with the given index id. Behaviour is unspecified + // if the index id or the storage manager are incorrect. + // Dimension VT_ULONG Dimensionality of the data that will be inserted. + // IndexCapacity VT_ULONG The index node capacity. Default is 100. + // LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. + // FillFactor VT_DOUBLE The fill factor. Default is 70% + // TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar + // NearMinimumOverlapFactor VT_ULONG Default is 32. + // SplitDistributionFactor VT_DOUBLE Default is 0.4 + // ReinsertFactor VT_DOUBLE Default is 0.3 + // EnsureTightMBRs VT_BOOL Default is true + // IndexPoolCapacity VT_LONG Default is 100 + // LeafPoolCapacity VT_LONG Default is 100 + // RegionPoolCapacity VT_LONG Default is 1000 + // PointPoolCapacity VT_LONG Default is 500 + + virtual ~RTree(); + + + + // + // ISpatialIndex interface + // + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type shapeIdentifier); + virtual bool deleteData(const IShape& shape, id_type id); + virtual void containsWhatQuery(const IShape& query, IVisitor& v); + virtual void intersectsWithQuery(const IShape& query, IVisitor& v); + virtual void pointLocationQuery(const Point& query, IVisitor& v); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator&); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v); + virtual void selfJoinQuery(const IShape& s, IVisitor& v); + virtual void queryStrategy(IQueryStrategy& qs); + virtual void getIndexProperties(Tools::PropertySet& out) const; + virtual void addCommand(ICommand* pCommand, CommandType ct); + virtual bool isIndexValid(); + virtual void getStatistics(IStatistics** out) const; + + private: + void initNew(Tools::PropertySet&); + void initOld(Tools::PropertySet& ps); + void storeHeader(); + void loadHeader(); + + void insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id); + void insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id, uint32_t level, byte* overflowTable); + bool deleteData_impl(const Region& mbr, id_type id); + + id_type writeNode(Node*); + NodePtr readNode(id_type page); + void deleteNode(Node*); + + void rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v); + void selfJoinQuery(id_type id1, id_type id2, const Region& r, IVisitor& vis); + + IStorageManager* m_pStorageManager; + + id_type m_rootID, m_headerID; + + RTreeVariant m_treeVariant; + + double m_fillFactor; + + uint32_t m_indexCapacity; + + uint32_t m_leafCapacity; + + uint32_t m_nearMinimumOverlapFactor; + // The R*-Tree 'p' constant, for calculating nearly minimum overlap cost. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.1] + + double m_splitDistributionFactor; + // The R*-Tree 'm' constant, for calculating spliting distributions. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.2] + + double m_reinsertFactor; + // The R*-Tree 'p' constant, for removing entries at reinserts. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.3] + + uint32_t m_dimension; + + Region m_infiniteRegion; + + Statistics m_stats; + + bool m_bTightMBRs; + + Tools::PointerPool<Point> m_pointPool; + Tools::PointerPool<Region> m_regionPool; + Tools::PointerPool<Node> m_indexPool; + Tools::PointerPool<Node> m_leafPool; + + std::vector<Tools::SmartPointer<ICommand> > m_writeNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_readNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_deleteNodeCommands; + +#ifdef HAVE_PTHREAD_H + pthread_rwlock_t m_rwLock; +#else + bool m_rwLock; +#endif + + + + + class NNEntry + { + public: + id_type m_id; + IEntry* m_pEntry; + double m_minDist; + + NNEntry(id_type id, IEntry* e, double f) : m_id(id), m_pEntry(e), m_minDist(f) {} + ~NNEntry() {} + + struct ascending : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_minDist > __y->m_minDist; } + }; + }; // NNEntry + + class NNComparator : public INearestNeighborComparator + { + public: + double getMinimumDistance(const IShape& query, const IShape& entry) + { + return query.getMinimumDistance(entry); + } + + double getMinimumDistance(const IShape& query, const IData& data) + { + IShape* pS; + data.getShape(&pS); + double ret = query.getMinimumDistance(*pS); + delete pS; + return ret; + } + }; // NNComparator + + class ValidateEntry + { + public: + ValidateEntry(Region& r, NodePtr& pNode) : m_parentMBR(r), m_pNode(pNode) {} + + Region m_parentMBR; + NodePtr m_pNode; + }; // ValidateEntry + + friend class Node; + friend class Leaf; + friend class Index; + friend class BulkLoader; + + friend std::ostream& operator<<(std::ostream& os, const RTree& t); + }; // RTree + + std::ostream& operator<<(std::ostream& os, const RTree& t); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Statistics.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Statistics.cc.svn-base new file mode 100644 index 000000000..d79e5097d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Statistics.cc.svn-base @@ -0,0 +1,172 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" + +#include "Statistics.h" + +using namespace SpatialIndex::RTree; + +Statistics::Statistics() +{ + reset(); +} + +Statistics::Statistics(const Statistics& s) +{ + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u32TreeHeight = s.m_u32TreeHeight; + m_nodesInLevel = s.m_nodesInLevel; +} + +Statistics::~Statistics() +{ +} + +Statistics& Statistics::operator=(const Statistics& s) +{ + if (this != &s) + { + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u32TreeHeight = s.m_u32TreeHeight; + m_nodesInLevel = s.m_nodesInLevel; + } + + return *this; +} + +uint64_t Statistics::getReads() const +{ + return m_u64Reads; +} + +uint64_t Statistics::getWrites() const +{ + return m_u64Writes; +} + +uint32_t Statistics::getNumberOfNodes() const +{ + return m_u32Nodes; +} + +uint64_t Statistics::getNumberOfData() const +{ + return m_u64Data; +} + +uint64_t Statistics::getSplits() const +{ + return m_u64Splits; +} + +uint64_t Statistics::getHits() const +{ + return m_u64Hits; +} + +uint64_t Statistics::getMisses() const +{ + return m_u64Misses; +} + +uint64_t Statistics::getAdjustments() const +{ + return m_u64Adjustments; +} + +uint64_t Statistics::getQueryResults() const +{ + return m_u64QueryResults; +} + +uint32_t Statistics::getTreeHeight() const +{ + return m_u32TreeHeight; +} + +uint32_t Statistics::getNumberOfNodesInLevel(uint32_t l) const +{ + uint32_t u32Nodes; + try + { + u32Nodes = m_nodesInLevel.at(l); + } + catch (...) + { + throw Tools::IndexOutOfBoundsException(l); + } + + return u32Nodes; +} + +void Statistics::reset() +{ + m_u64Reads = 0; + m_u64Writes = 0; + m_u64Splits = 0; + m_u64Hits = 0; + m_u64Misses = 0; + m_u32Nodes = 0; + m_u64Adjustments = 0; + m_u64QueryResults = 0; + m_u64Data = 0; + m_u32TreeHeight = 0; + m_nodesInLevel.clear(); +} + +std::ostream& SpatialIndex::RTree::operator<<(std::ostream& os, const Statistics& s) +{ + os << "Reads: " << s.m_u64Reads << std::endl + << "Writes: " << s.m_u64Writes << std::endl + << "Hits: " << s.m_u64Hits << std::endl + << "Misses: " << s.m_u64Misses << std::endl + << "Tree height: " << s.m_u32TreeHeight << std::endl + << "Number of data: " << s.m_u64Data << std::endl + << "Number of nodes: " << s.m_u32Nodes << std::endl; + + for (uint32_t u32Level = 0; u32Level < s.m_u32TreeHeight; ++u32Level) + { + os << "Level " << u32Level << " pages: " << s.m_nodesInLevel[u32Level] << std::endl; + } + + os << "Splits: " << s.m_u64Splits << std::endl + << "Adjustments: " << s.m_u64Adjustments << std::endl + << "Query results: " << s.m_u64QueryResults << std::endl; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Statistics.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Statistics.h.svn-base new file mode 100644 index 000000000..389726d88 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/.svn/text-base/Statistics.h.svn-base @@ -0,0 +1,93 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class RTree; + class Node; + class Leaf; + class Index; + + class Statistics : public SpatialIndex::IStatistics + { + public: + Statistics(); + Statistics(const Statistics&); + virtual ~Statistics(); + Statistics& operator=(const Statistics&); + + // + // IStatistics interface + // + virtual uint64_t getReads() const; + virtual uint64_t getWrites() const; + virtual uint32_t getNumberOfNodes() const; + virtual uint64_t getNumberOfData() const; + + virtual uint64_t getSplits() const; + virtual uint64_t getHits() const; + virtual uint64_t getMisses() const; + virtual uint64_t getAdjustments() const; + virtual uint64_t getQueryResults() const; + virtual uint32_t getTreeHeight() const; + virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const; + + private: + void reset(); + + uint64_t m_u64Reads; + + uint64_t m_u64Writes; + + uint64_t m_u64Splits; + + uint64_t m_u64Hits; + + uint64_t m_u64Misses; + + uint32_t m_u32Nodes; + + uint64_t m_u64Adjustments; + + uint64_t m_u64QueryResults; + + uint64_t m_u64Data; + + uint32_t m_u32TreeHeight; + + std::vector<uint32_t> m_nodesInLevel; + + friend class RTree; + friend class Node; + friend class Index; + friend class Leaf; + friend class BulkLoader; + + friend std::ostream& operator<<(std::ostream& os, const Statistics& s); + }; // Statistics + + std::ostream& operator<<(std::ostream& os, const Statistics& s); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/BulkLoader.cc b/sci-libs/libspatialindex/svn/trunk/src/rtree/BulkLoader.cc new file mode 100644 index 000000000..5fb14963d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/BulkLoader.cc @@ -0,0 +1,458 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <stdio.h> +#include <cmath> + +#ifndef _MSC_VER +#include <unistd.h> +#endif + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Leaf.h" +#include "Index.h" +#include "BulkLoader.h" + +using namespace SpatialIndex::RTree; + +// +// ExternalSorter::Record +// +ExternalSorter::Record::Record() +: m_pData(0) +{ +} + +ExternalSorter::Record::Record(const Region& r, id_type id, uint32_t len, byte* pData, uint32_t s) +: m_r(r), m_id(id), m_len(len), m_pData(pData), m_s(s) +{ +} + +ExternalSorter::Record::~Record() +{ + delete[] m_pData; +} + +bool ExternalSorter::Record::operator<(const Record& r) const +{ + if (m_s != r.m_s) + throw Tools::IllegalStateException("ExternalSorter::Record::operator<: Incompatible sorting dimensions."); + + if (m_r.m_pHigh[m_s] + m_r.m_pLow[m_s] < r.m_r.m_pHigh[m_s] + r.m_r.m_pLow[m_s]) + return true; + else + return false; +} + +void ExternalSorter::Record::storeToFile(Tools::TemporaryFile& f) +{ + f.write(static_cast<uint64_t>(m_id)); + f.write(m_r.m_dimension); + f.write(m_s); + + for (uint32_t i = 0; i < m_r.m_dimension; ++i) + { + f.write(m_r.m_pLow[i]); + f.write(m_r.m_pHigh[i]); + } + + f.write(m_len); + if (m_len > 0) f.write(m_len, m_pData); +} + +void ExternalSorter::Record::loadFromFile(Tools::TemporaryFile& f) +{ + m_id = static_cast<id_type>(f.readUInt64()); + uint32_t dim = f.readUInt32(); + m_s = f.readUInt32(); + + if (dim != m_r.m_dimension) + { + delete[] m_r.m_pLow; + delete[] m_r.m_pHigh; + m_r.m_dimension = dim; + m_r.m_pLow = new double[dim]; + m_r.m_pHigh = new double[dim]; + } + + for (uint32_t i = 0; i < m_r.m_dimension; ++i) + { + m_r.m_pLow[i] = f.readDouble(); + m_r.m_pHigh[i] = f.readDouble(); + } + + m_len = f.readUInt32(); + delete[] m_pData; m_pData = 0; + if (m_len > 0) f.readBytes(m_len, &m_pData); +} + +// +// ExternalSorter +// +ExternalSorter::ExternalSorter(uint32_t u32PageSize, uint32_t u32BufferPages) +: m_bInsertionPhase(true), m_u32PageSize(u32PageSize), + m_u32BufferPages(u32BufferPages), m_u64TotalEntries(0), m_stI(0) +{ +} + +ExternalSorter::~ExternalSorter() +{ + for (m_stI = 0; m_stI < m_buffer.size(); ++m_stI) delete m_buffer[m_stI]; +} + +void ExternalSorter::insert(Record* r) +{ + if (m_bInsertionPhase == false) + throw Tools::IllegalStateException("ExternalSorter::insert: Input has already been sorted."); + + m_buffer.push_back(r); + ++m_u64TotalEntries; + + // this will create the initial, sorted buckets before the + // external merge sort. + if (m_buffer.size() >= m_u32PageSize * m_u32BufferPages) + { + std::sort(m_buffer.begin(), m_buffer.end(), Record::SortAscending()); + Tools::TemporaryFile* tf = new Tools::TemporaryFile(); + for (size_t j = 0; j < m_buffer.size(); ++j) + { + m_buffer[j]->storeToFile(*tf); + delete m_buffer[j]; + } + m_buffer.clear(); + tf->rewindForReading(); + m_runs.push_back(Tools::SmartPointer<Tools::TemporaryFile>(tf)); + } +} + +void ExternalSorter::sort() +{ + if (m_bInsertionPhase == false) + throw Tools::IllegalStateException("ExternalSorter::sort: Input has already been sorted."); + + if (m_runs.empty()) + { + // The data fits in main memory. No need to store to disk. + std::sort(m_buffer.begin(), m_buffer.end(), Record::SortAscending()); + m_bInsertionPhase = false; + return; + } + + if (m_buffer.size() > 0) + { + // Whatever remained in the buffer (if not filled) needs to be stored + // as the final bucket. + std::sort(m_buffer.begin(), m_buffer.end(), Record::SortAscending()); + Tools::TemporaryFile* tf = new Tools::TemporaryFile(); + for (size_t j = 0; j < m_buffer.size(); ++j) + { + m_buffer[j]->storeToFile(*tf); + delete m_buffer[j]; + } + m_buffer.clear(); + tf->rewindForReading(); + m_runs.push_back(Tools::SmartPointer<Tools::TemporaryFile>(tf)); + } + + if (m_runs.size() == 1) + { + m_sortedFile = m_runs.front(); + } + else + { + Record* r; + + while (m_runs.size() > 1) + { + Tools::SmartPointer<Tools::TemporaryFile> tf(new Tools::TemporaryFile()); + std::vector<Tools::SmartPointer<Tools::TemporaryFile> > buckets; + std::vector<std::queue<Record*> > buffers; + std::priority_queue<PQEntry, std::vector<PQEntry>, PQEntry::SortAscending> pq; + + // initialize buffers and priority queue. + std::list<Tools::SmartPointer<Tools::TemporaryFile> >::iterator it = m_runs.begin(); + for (uint32_t i = 0; i < (std::min)(static_cast<uint32_t>(m_runs.size()), m_u32BufferPages); ++i) + { + buckets.push_back(*it); + buffers.push_back(std::queue<Record*>()); + + r = new Record(); + r->loadFromFile(**it); + // a run cannot be empty initially, so this should never fail. + pq.push(PQEntry(r, i)); + + for (uint32_t j = 0; j < m_u32PageSize - 1; ++j) + { + // fill the buffer with the rest of the page of records. + try + { + r = new Record(); + r->loadFromFile(**it); + buffers.back().push(r); + } + catch (Tools::EndOfStreamException) + { + delete r; + break; + } + } + ++it; + } + + // exhaust buckets, buffers, and priority queue. + while (! pq.empty()) + { + PQEntry e = pq.top(); pq.pop(); + e.m_r->storeToFile(*tf); + delete e.m_r; + + if (! buckets[e.m_u32Index]->eof() && buffers[e.m_u32Index].empty()) + { + for (uint32_t j = 0; j < m_u32PageSize; ++j) + { + try + { + r = new Record(); + r->loadFromFile(*buckets[e.m_u32Index]); + buffers[e.m_u32Index].push(r); + } + catch (Tools::EndOfStreamException) + { + delete r; + break; + } + } + } + + if (! buffers[e.m_u32Index].empty()) + { + e.m_r = buffers[e.m_u32Index].front(); + buffers[e.m_u32Index].pop(); + pq.push(e); + } + } + + tf->rewindForReading(); + + // check if another pass is needed. + uint32_t u32Count = std::min(static_cast<uint32_t>(m_runs.size()), m_u32BufferPages); + for (uint32_t i = 0; i < u32Count; ++i) + { + m_runs.pop_front(); + } + + if (m_runs.size() == 0) + { + m_sortedFile = tf; + break; + } + else + { + m_runs.push_back(tf); + } + } + } + + m_bInsertionPhase = false; +} + +ExternalSorter::Record* ExternalSorter::getNextRecord() +{ + if (m_bInsertionPhase == true) + throw Tools::IllegalStateException("ExternalSorter::getNextRecord: Input has not been sorted yet."); + + Record* ret; + + if (m_sortedFile.get() == 0) + { + if (m_stI < m_buffer.size()) + { + ret = m_buffer[m_stI]; + m_buffer[m_stI] = 0; + ++m_stI; + } + else + throw Tools::EndOfStreamException(""); + } + else + { + ret = new Record(); + ret->loadFromFile(*m_sortedFile); + } + + return ret; +} + +inline uint64_t ExternalSorter::getTotalEntries() const +{ + return m_u64TotalEntries; +} + +// +// BulkLoader +// +void BulkLoader::bulkLoadUsingSTR( + SpatialIndex::RTree::RTree* pTree, + IDataStream& stream, + uint32_t bindex, + uint32_t bleaf, + uint32_t pageSize, + uint32_t numberOfPages +) { + if (! stream.hasNext()) + throw Tools::IllegalArgumentException( + "RTree::BulkLoader::bulkLoadUsingSTR: Empty data stream given." + ); + + NodePtr n = pTree->readNode(pTree->m_rootID); + pTree->deleteNode(n.get()); + + #ifndef NDEBUG + std::cerr << "RTree::BulkLoader: Sorting data." << std::endl; + #endif + + Tools::SmartPointer<ExternalSorter> es = Tools::SmartPointer<ExternalSorter>(new ExternalSorter(pageSize, numberOfPages)); + + while (stream.hasNext()) + { + Data* d = reinterpret_cast<Data*>(stream.getNext()); + if (d == 0) + throw Tools::IllegalArgumentException( + "bulkLoadUsingSTR: RTree bulk load expects SpatialIndex::RTree::Data entries." + ); + + es->insert(new ExternalSorter::Record(d->m_region, d->m_id, d->m_dataLength, d->m_pData, 0)); + d->m_pData = 0; + delete d; + } + es->sort(); + + pTree->m_stats.m_u64Data = es->getTotalEntries(); + + // create index levels. + uint32_t level = 0; + + while (true) + { + #ifndef NDEBUG + std::cerr << "RTree::BulkLoader: Building level " << level << std::endl; + #endif + + pTree->m_stats.m_nodesInLevel.push_back(0); + + Tools::SmartPointer<ExternalSorter> es2 = Tools::SmartPointer<ExternalSorter>(new ExternalSorter(pageSize, numberOfPages)); + createLevel(pTree, es, 0, bleaf, bindex, level++, es2, pageSize, numberOfPages); + es = es2; + + if (es->getTotalEntries() == 1) break; + es->sort(); + } + + pTree->m_stats.m_u32TreeHeight = level; + pTree->storeHeader(); +} + +void BulkLoader::createLevel( + SpatialIndex::RTree::RTree* pTree, + Tools::SmartPointer<ExternalSorter> es, + uint32_t dimension, + uint32_t bleaf, + uint32_t bindex, + uint32_t level, + Tools::SmartPointer<ExternalSorter> es2, + uint32_t pageSize, + uint32_t numberOfPages +) { + uint64_t b = (level == 0) ? bleaf : bindex; + uint64_t P = static_cast<uint64_t>(std::ceil(static_cast<double>(es->getTotalEntries()) / static_cast<double>(b))); + uint64_t S = static_cast<uint64_t>(std::ceil(std::sqrt(static_cast<double>(P)))); + + if (S == 1 || dimension == pTree->m_dimension - 1 || S * b == es->getTotalEntries()) + { + std::vector<ExternalSorter::Record*> node; + ExternalSorter::Record* r; + + while (true) + { + try { r = es->getNextRecord(); } catch (Tools::EndOfStreamException) { break; } + node.push_back(r); + + if (node.size() == b) + { + Node* n = createNode(pTree, node, level); + node.clear(); + pTree->writeNode(n); + es2->insert(new ExternalSorter::Record(n->m_nodeMBR, n->m_identifier, 0, 0, 0)); + pTree->m_rootID = n->m_identifier; + // special case when the root has exactly bindex entries. + delete n; + } + } + + if (! node.empty()) + { + Node* n = createNode(pTree, node, level); + pTree->writeNode(n); + es2->insert(new ExternalSorter::Record(n->m_nodeMBR, n->m_identifier, 0, 0, 0)); + pTree->m_rootID = n->m_identifier; + delete n; + } + } + else + { + bool bMore = true; + + while (bMore) + { + ExternalSorter::Record* pR; + Tools::SmartPointer<ExternalSorter> es3 = Tools::SmartPointer<ExternalSorter>(new ExternalSorter(pageSize, numberOfPages)); + + for (uint64_t i = 0; i < S * b; ++i) + { + try { pR = es->getNextRecord(); } + catch (Tools::EndOfStreamException) { bMore = false; break; } + pR->m_s = dimension + 1; + es3->insert(pR); + } + es3->sort(); + createLevel(pTree, es3, dimension + 1, bleaf, bindex, level, es2, pageSize, numberOfPages); + } + } +} + +Node* BulkLoader::createNode(SpatialIndex::RTree::RTree* pTree, std::vector<ExternalSorter::Record*>& e, uint32_t level) +{ + Node* n; + + if (level == 0) n = new Leaf(pTree, -1); + else n = new Index(pTree, -1, level); + + for (size_t cChild = 0; cChild < e.size(); ++cChild) + { + n->insertEntry(e[cChild]->m_len, e[cChild]->m_pData, e[cChild]->m_r, e[cChild]->m_id); + e[cChild]->m_pData = 0; + delete e[cChild]; + } + + return n; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/BulkLoader.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/BulkLoader.h new file mode 100644 index 000000000..17d8f71fb --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/BulkLoader.h @@ -0,0 +1,131 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class ExternalSorter + { + public: + class Record + { + public: + Record(); + Record(const Region& r, id_type id, uint32_t len, byte* pData, uint32_t s); + ~Record(); + + bool operator<(const Record& r) const; + + void storeToFile(Tools::TemporaryFile& f); + void loadFromFile(Tools::TemporaryFile& f); + + struct SortAscending : public std::binary_function<Record* const, Record* const, bool> + { + bool operator()(Record* const r1, Record* const r2) + { + if (*r1 < *r2) return true; + else return false; + } + }; + + public: + Region m_r; + id_type m_id; + byte* m_pData; + uint32_t m_len; + uint32_t m_s; + }; + + public: + ExternalSorter(uint32_t u32PageSize, uint32_t u32BufferPages); + virtual ~ExternalSorter(); + + void insert(Record* r); + void sort(); + Record* getNextRecord(); + uint64_t getTotalEntries() const; + + private: + class PQEntry + { + public: + PQEntry(Record* r, uint32_t u32Index) : m_r(r), m_u32Index(u32Index) {} + + struct SortAscending : public std::binary_function<const PQEntry&, const PQEntry&, bool> + { + bool operator()(const PQEntry& e1, const PQEntry& e2) + { + if (*(e1.m_r) < *(e2.m_r)) return true; + else return false; + } + }; + + Record* m_r; + uint32_t m_u32Index; + }; + + private: + bool m_bInsertionPhase; + uint32_t m_u32PageSize; + uint32_t m_u32BufferPages; + Tools::SmartPointer<Tools::TemporaryFile> m_sortedFile; + std::list<Tools::SmartPointer<Tools::TemporaryFile> > m_runs; + std::vector<Record*> m_buffer; + uint64_t m_u64TotalEntries; + uint32_t m_stI; + }; + + class BulkLoader + { + public: + void bulkLoadUsingSTR( + RTree* pTree, + IDataStream& stream, + uint32_t bindex, + uint32_t bleaf, + uint32_t pageSize, // The number of node entries per page. + uint32_t numberOfPages // The total number of pages to use. + ); + + protected: + void createLevel( + RTree* pTree, + Tools::SmartPointer<ExternalSorter> es, + uint32_t dimension, + uint32_t indexSize, + uint32_t leafSize, + uint32_t level, + Tools::SmartPointer<ExternalSorter> es2, + uint32_t pageSize, + uint32_t numberOfPages + ); + + Node* createNode( + RTree* pTree, + std::vector<ExternalSorter::Record*>& e, + uint32_t level + ); + }; + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Index.cc b/sci-libs/libspatialindex/svn/trunk/src/rtree/Index.cc new file mode 100644 index 000000000..9a3209683 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Index.cc @@ -0,0 +1,372 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" + +using namespace SpatialIndex::RTree; + +Index::~Index() +{ +} + +Index::Index(SpatialIndex::RTree::RTree* pTree, id_type id, uint32_t level) : Node(pTree, id, level, pTree->m_indexCapacity) +{ +} + +NodePtr Index::chooseSubtree(const Region& mbr, uint32_t insertionLevel, std::stack<id_type>& pathBuffer) +{ + if (m_level == insertionLevel) return NodePtr(this, &(m_pTree->m_indexPool)); + + pathBuffer.push(m_identifier); + + uint32_t child = 0; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + child = findLeastEnlargement(mbr); + break; + case RV_RSTAR: + if (m_level == 1) + { + // if this node points to leaves... + child = findLeastOverlap(mbr); + } + else + { + child = findLeastEnlargement(mbr); + } + break; + default: + throw Tools::NotSupportedException("Index::chooseSubtree: Tree variant not supported."); + } + assert(child != std::numeric_limits<uint32_t>::max()); + + NodePtr n = m_pTree->readNode(m_pIdentifier[child]); + NodePtr ret = n->chooseSubtree(mbr, insertionLevel, pathBuffer); + assert(n.unique()); + if (ret.get() == n.get()) n.relinquish(); + + return ret; +} + +NodePtr Index::findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_ptrMBR[cChild]->containsRegion(mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findLeaf(mbr, id, pathBuffer); + if (n.get() == l.get()) n.relinquish(); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} + +void Index::split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& ptrLeft, NodePtr& ptrRight) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Index::split: Tree variant not supported."); + } + + ptrLeft = m_pTree->m_indexPool.acquire(); + ptrRight = m_pTree->m_indexPool.acquire(); + + if (ptrLeft.get() == 0) ptrLeft = NodePtr(new Index(m_pTree, m_identifier, m_level), &(m_pTree->m_indexPool)); + if (ptrRight.get() == 0) ptrRight = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + + ptrLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + ptrRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + ptrLeft->insertEntry(0, 0, *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + ptrRight->insertEntry(0, 0, *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + } +} + +uint32_t Index::findLeastEnlargement(const Region& r) const +{ + double area = std::numeric_limits<double>::max(); + uint32_t best = std::numeric_limits<uint32_t>::max(); + + RegionPtr t = m_pTree->m_regionPool.acquire(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_ptrMBR[cChild]->getCombinedRegion(*t, r); + + double a = m_ptrMBR[cChild]->getArea(); + double enl = t->getArea() - a; + + if (enl < area) + { + area = enl; + best = cChild; + } + else if (enl == area) + { + // this will rarely happen, so compute best area on the fly only + // when necessary. + if (a < m_ptrMBR[best]->getArea()) best = cChild; + } + } + + return best; +} + +uint32_t Index::findLeastOverlap(const Region& r) const +{ + OverlapEntry** entries = new OverlapEntry*[m_children]; + + double leastOverlap = std::numeric_limits<double>::max(); + double me = std::numeric_limits<double>::max(); + OverlapEntry* best = 0; + + // find combined region and enlargement of every entry and store it. + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + try + { + entries[cChild] = new OverlapEntry(); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete entries[i]; + delete[] entries; + throw; + } + + entries[cChild]->m_index = cChild; + entries[cChild]->m_original = m_ptrMBR[cChild]; + entries[cChild]->m_combined = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->getCombinedRegion(*(entries[cChild]->m_combined), r); + entries[cChild]->m_oa = entries[cChild]->m_original->getArea(); + entries[cChild]->m_ca = entries[cChild]->m_combined->getArea(); + entries[cChild]->m_enlargement = entries[cChild]->m_ca - entries[cChild]->m_oa; + + if (entries[cChild]->m_enlargement < me) + { + me = entries[cChild]->m_enlargement; + best = entries[cChild]; + } + else if (entries[cChild]->m_enlargement == me && entries[cChild]->m_oa < best->m_oa) + { + best = entries[cChild]; + } + } + + if (me < -std::numeric_limits<double>::epsilon() || me > std::numeric_limits<double>::epsilon()) + { + uint32_t cIterations; + + if (m_children > m_pTree->m_nearMinimumOverlapFactor) + { + // sort entries in increasing order of enlargement. + ::qsort(entries, m_children, + sizeof(OverlapEntry*), + OverlapEntry::compareEntries); + assert(entries[0]->m_enlargement <= entries[m_children - 1]->m_enlargement); + + cIterations = m_pTree->m_nearMinimumOverlapFactor; + } + else + { + cIterations = m_children; + } + + // calculate overlap of most important original entries (near minimum overlap cost). + for (uint32_t cIndex = 0; cIndex < cIterations; ++cIndex) + { + double dif = 0.0; + OverlapEntry* e = entries[cIndex]; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (e->m_index != cChild) + { + double f = e->m_combined->getIntersectingArea(*(m_ptrMBR[cChild])); + if (f != 0.0) dif += f - e->m_original->getIntersectingArea(*(m_ptrMBR[cChild])); + } + } // for (cChild) + + if (dif < leastOverlap) + { + leastOverlap = dif; + best = entries[cIndex]; + } + else if (dif == leastOverlap) + { + if (e->m_enlargement == best->m_enlargement) + { + // keep the one with least area. + if (e->m_original->getArea() < best->m_original->getArea()) best = entries[cIndex]; + } + else + { + // keep the one with least enlargement. + if (e->m_enlargement < best->m_enlargement) best = entries[cIndex]; + } + } + } // for (cIndex) + } + + uint32_t ret = best->m_index; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + delete entries[cChild]; + } + delete[] entries; + + return ret; +} + +void Index::adjustTree(Node* n, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n->m_identifier) break; + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + bool bContained = m_nodeMBR.containsRegion(n->m_nodeMBR); + bool bTouches = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool bRecompute = (! bContained || (bTouches && m_pTree->m_bTightMBRs)); + + *(m_ptrMBR[child]) = n->m_nodeMBR; + + if (bRecompute) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + m_pTree->writeNode(this); + + if (bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} + +void Index::adjustTree(Node* n1, Node* n2, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + ++(m_pTree->m_stats.m_u64Adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n1->m_identifier) break; + } + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + bool bContained = m_nodeMBR.containsRegion(n1->m_nodeMBR); + bool bTouches = m_nodeMBR.touchesRegion(*(m_ptrMBR[child])); + bool bRecompute = (! bContained || (bTouches && m_pTree->m_bTightMBRs)); + + *(m_ptrMBR[child]) = n1->m_nodeMBR; + + if (bRecompute) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + } + + // No write necessary here. insertData will write the node if needed. + //m_pTree->writeNode(this); + + bool bAdjusted = insertData(0, 0, n2->m_nodeMBR, n2->m_identifier, pathBuffer, overflowTable); + + // if n2 is contained in the node and there was no split or reinsert, + // we need to adjust only if recalculation took place. + // In all other cases insertData above took care of adjustment. + if ((! bAdjusted) && bRecompute && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Index.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/Index.h new file mode 100644 index 000000000..ce0510dff --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Index.h @@ -0,0 +1,73 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class Index : public Node + { + public: + virtual ~Index(); + + protected: + Index(RTree* pTree, id_type id, uint32_t level); + + virtual NodePtr chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& left, NodePtr& right); + + uint32_t findLeastEnlargement(const Region&) const; + uint32_t findLeastOverlap(const Region&) const; + + void adjustTree(Node*, std::stack<id_type>&); + void adjustTree(Node*, Node*, std::stack<id_type>&, byte* overflowTable); + + class OverlapEntry + { + public: + uint32_t m_index; + double m_enlargement; + RegionPtr m_original; + RegionPtr m_combined; + double m_oa; + double m_ca; + + static int compareEntries(const void* pv1, const void* pv2) + { + OverlapEntry* pe1 = * (OverlapEntry**) pv1; + OverlapEntry* pe2 = * (OverlapEntry**) pv2; + + if (pe1->m_enlargement < pe2->m_enlargement) return -1; + if (pe1->m_enlargement > pe2->m_enlargement) return 1; + return 0; + } + }; // OverlapEntry + + friend class RTree; + friend class Node; + friend class BulkLoader; + }; // Index + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Leaf.cc b/sci-libs/libspatialindex/svn/trunk/src/rtree/Leaf.cc new file mode 100644 index 000000000..5781734d5 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Leaf.cc @@ -0,0 +1,138 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::RTree; + +Leaf::~Leaf() +{ +} + +Leaf::Leaf(SpatialIndex::RTree::RTree* pTree, id_type id): Node(pTree, id, 0, pTree->m_leafCapacity) +{ +} + +NodePtr Leaf::chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer) +{ + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + return NodePtr(this, &(m_pTree->m_leafPool)); +} + +NodePtr Leaf::findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + if (m_pIdentifier[cChild] == id && mbr == *(m_ptrMBR[cChild])) return NodePtr(this, &(m_pTree->m_leafPool)); + } + + return NodePtr(); +} + +void Leaf::split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight) +{ + ++(m_pTree->m_stats.m_u64Splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_QUADRATIC: + rtreeSplit(dataLength, pData, mbr, id, g1, g2); + break; + case RV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Leaf::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_leafPool.acquire(); + pRight = m_pTree->m_leafPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + if (pRight.get() == 0) pRight = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(m_pDataLength[g1[cIndex]], m_pData[g1[cIndex]], *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g1[cIndex]] = 0; + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(m_pDataLength[g2[cIndex]], m_pData[g2[cIndex]], *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g2[cIndex]] = 0; + } +} + +void Leaf::deleteData(id_type id, std::stack<id_type>& pathBuffer) +{ + uint32_t child; + + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == id) break; + } + + deleteEntry(child); + m_pTree->writeNode(this); + + std::stack<NodePtr> toReinsert; + NodePtr ptrThis(this, &(m_pTree->m_leafPool)); + condenseTree(toReinsert, pathBuffer, ptrThis); + ptrThis.relinquish(); + + // re-insert eliminated nodes. + while (! toReinsert.empty()) + { + NodePtr n = toReinsert.top(); toReinsert.pop(); + m_pTree->deleteNode(n.get()); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + // keep this in the for loop. The tree height might change after insertions. + byte* overflowTable = new byte[m_pTree->m_stats.m_u32TreeHeight]; + bzero(overflowTable, m_pTree->m_stats.m_u32TreeHeight); + m_pTree->insertData_impl(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild], n->m_level, overflowTable); + n->m_pData[cChild] = 0; + delete[] overflowTable; + } + if (n.get() == this) n.relinquish(); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Leaf.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/Leaf.h new file mode 100644 index 000000000..2705e4c1d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Leaf.h @@ -0,0 +1,47 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class Leaf : public Node + { + public: + virtual ~Leaf(); + + protected: + Leaf(RTree* pTree, id_type id); + + virtual NodePtr chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& left, NodePtr& right); + + virtual void deleteData(id_type id, std::stack<id_type>& pathBuffer); + + friend class RTree; + friend class BulkLoader; + }; // Leaf + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/rtree/Makefile.am new file mode 100644 index 000000000..e1bcd6272 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Makefile.am @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = librtree.la +INCLUDES = -I../../include +librtree_la_SOURCES = BulkLoader.cc Index.cc Leaf.cc Node.cc RTree.cc Statistics.cc BulkLoader.h Index.h Leaf.h Node.h PointerPoolNode.h RTree.h Statistics.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Node.cc b/sci-libs/libspatialindex/svn/trunk/src/rtree/Node.cc new file mode 100644 index 000000000..09ecfe943 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Node.cc @@ -0,0 +1,1074 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RTree.h" +#include "Node.h" +#include "Index.h" + +using namespace SpatialIndex::RTree; + +// +// Tools::IObject interface +// +Tools::IObject* Node::clone() +{ + throw Tools::NotSupportedException("IObject::clone should never be called."); +} + +// +// Tools::ISerializable interface +// +uint32_t Node::getByteArraySize() +{ + return + (sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + (m_children * (m_pTree->m_dimension * sizeof(double) * 2 + sizeof(id_type) + sizeof(uint32_t))) + + m_totalDataLength + + (2 * m_pTree->m_dimension * sizeof(double))); +} + +void Node::loadFromByteArray(const byte* ptr) +{ + m_nodeMBR = m_pTree->m_infiniteRegion; + + // skip the node type information, it is not needed. + ptr += sizeof(uint32_t); + + memcpy(&m_level, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&m_children, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + m_ptrMBR[u32Child] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[u32Child]) = m_pTree->m_infiniteRegion; + + memcpy(m_ptrMBR[u32Child]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[u32Child]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(&(m_pIdentifier[u32Child]), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(&(m_pDataLength[u32Child]), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[u32Child] > 0) + { + m_totalDataLength += m_pDataLength[u32Child]; + m_pData[u32Child] = new byte[m_pDataLength[u32Child]]; + memcpy(m_pData[u32Child], ptr, m_pDataLength[u32Child]); + ptr += m_pDataLength[u32Child]; + } + else + { + m_pData[u32Child] = 0; + } + + //m_nodeMBR.combineRegion(*(m_ptrMBR[u32Child])); + } + + memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +void Node::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + + *data = new byte[len]; + byte* ptr = *data; + + uint32_t nodeType; + + if (m_level == 0) nodeType = PersistentLeaf; + else nodeType = PersistentIndex; + + memcpy(ptr, &nodeType, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_level, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_children, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + memcpy(ptr, m_ptrMBR[u32Child]->m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[u32Child]->m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, &(m_pIdentifier[u32Child]), sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(ptr, &(m_pDataLength[u32Child]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[u32Child] > 0) + { + memcpy(ptr, m_pData[u32Child], m_pDataLength[u32Child]); + ptr += m_pDataLength[u32Child]; + } + } + + // store the node MBR for efficiency. This increases the node size a little bit. + memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); + + assert(len == (ptr - *data) + m_pTree->m_dimension * sizeof(double)); +} + +// +// SpatialIndex::IEntry interface +// +SpatialIndex::id_type Node::getIdentifier() const +{ + return m_identifier; +} + +void Node::getShape(IShape** out) const +{ + *out = new Region(m_nodeMBR); +} + +// +// SpatialIndex::INode interface +// +uint32_t Node::getChildrenCount() const +{ + return m_children; +} + +SpatialIndex::id_type Node::getChildIdentifier(uint32_t index) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + return m_pIdentifier[index]; +} + +void Node::getChildShape(uint32_t index, IShape** out) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + *out = new Region(*(m_ptrMBR[index])); +} + +void Node::getChildData(uint32_t index, uint32_t& length, byte** data) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + if (m_pData[index] == NULL) + { + length = 0; + data = NULL; + } + else + { + length = m_pDataLength[index]; + *data = m_pData[index]; + } +} + +uint32_t Node::getLevel() const +{ + return m_level; +} + +bool Node::isLeaf() const +{ + return (m_level == 0); +} + +bool Node::isIndex() const +{ + return (m_level != 0); +} + +// +// Internal +// + +Node::Node() : + m_pTree(0), + m_level(0), + m_identifier(-1), + m_children(0), + m_capacity(0), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ +} + +Node::Node(SpatialIndex::RTree::RTree* pTree, id_type id, uint32_t level, uint32_t capacity) : + m_pTree(pTree), + m_level(level), + m_identifier(id), + m_children(0), + m_capacity(capacity), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ + m_nodeMBR.makeInfinite(m_pTree->m_dimension); + + try + { + m_pDataLength = new uint32_t[m_capacity + 1]; + m_pData = new byte*[m_capacity + 1]; + m_ptrMBR = new RegionPtr[m_capacity + 1]; + m_pIdentifier = new id_type[m_capacity + 1]; + } + catch (...) + { + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + throw; + } +} + +Node::~Node() +{ + if (m_pData != 0) + { + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + if (m_pData[u32Child] != 0) delete[] m_pData[u32Child]; + } + + delete[] m_pData; + } + + delete[] m_pDataLength; + delete[] m_ptrMBR; + delete[] m_pIdentifier; +} + +Node& Node::operator=(const Node& n) +{ + throw Tools::IllegalStateException("operator =: This should never be called."); +} + +void Node::insertEntry(uint32_t dataLength, byte* pData, Region& mbr, id_type id) +{ + assert(m_children < m_capacity); + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + m_totalDataLength += dataLength; + ++m_children; + + m_nodeMBR.combineRegion(mbr); +} + +void Node::deleteEntry(uint32_t index) +{ + assert(index >= 0 && index < m_children); + + // cache it, since I might need it for "touches" later. + RegionPtr ptrR = m_ptrMBR[index]; + + m_totalDataLength -= m_pDataLength[index]; + if (m_pData[index] != 0) delete[] m_pData[index]; + + if (m_children > 1 && index != m_children - 1) + { + m_pDataLength[index] = m_pDataLength[m_children - 1]; + m_pData[index] = m_pData[m_children - 1]; + m_ptrMBR[index] = m_ptrMBR[m_children - 1]; + m_pIdentifier[index] = m_pIdentifier[m_children - 1]; + } + + --m_children; + + // WARNING: index has now changed. Do not use it below here. + + if (m_children == 0) + { + m_nodeMBR = m_pTree->m_infiniteRegion; + } + else if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesRegion(*ptrR)) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[u32Child]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[u32Child]->m_pHigh[cDim]); + } + } + } +} + +bool Node::insertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + if (m_children < m_capacity) + { + bool adjusted = false; + + // this has to happen before insertEntry modifies m_nodeMBR. + bool b = m_nodeMBR.containsRegion(mbr); + + insertEntry(dataLength, pData, mbr, id); + m_pTree->writeNode(this); + + if ((! b) && (! pathBuffer.empty())) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + adjusted = true; + } + + return adjusted; + } + else if (m_pTree->m_treeVariant == RV_RSTAR && (! pathBuffer.empty()) && overflowTable[m_level] == 0) + { + overflowTable[m_level] = 1; + + std::vector<uint32_t> vReinsert, vKeep; + reinsertData(dataLength, pData, mbr, id, vReinsert, vKeep); + + uint32_t lReinsert = static_cast<uint32_t>(vReinsert.size()); + uint32_t lKeep = static_cast<uint32_t>(vKeep.size()); + + byte** reinsertdata = 0; + RegionPtr* reinsertmbr = 0; + id_type* reinsertid = 0; + uint32_t* reinsertlen = 0; + byte** keepdata = 0; + RegionPtr* keepmbr = 0; + id_type* keepid = 0; + uint32_t* keeplen = 0; + + try + { + reinsertdata = new byte*[lReinsert]; + reinsertmbr = new RegionPtr[lReinsert]; + reinsertid = new id_type[lReinsert]; + reinsertlen = new uint32_t[lReinsert]; + + keepdata = new byte*[m_capacity + 1]; + keepmbr = new RegionPtr[m_capacity + 1]; + keepid = new id_type[m_capacity + 1]; + keeplen = new uint32_t[m_capacity + 1]; + } + catch (...) + { + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + delete[] keepdata; + delete[] keepmbr; + delete[] keepid; + delete[] keeplen; + throw; + } + + uint32_t cIndex; + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + reinsertlen[cIndex] = m_pDataLength[vReinsert[cIndex]]; + reinsertdata[cIndex] = m_pData[vReinsert[cIndex]]; + reinsertmbr[cIndex] = m_ptrMBR[vReinsert[cIndex]]; + reinsertid[cIndex] = m_pIdentifier[vReinsert[cIndex]]; + } + + for (cIndex = 0; cIndex < lKeep; ++cIndex) + { + keeplen[cIndex] = m_pDataLength[vKeep[cIndex]]; + keepdata[cIndex] = m_pData[vKeep[cIndex]]; + keepmbr[cIndex] = m_ptrMBR[vKeep[cIndex]]; + keepid[cIndex] = m_pIdentifier[vKeep[cIndex]]; + } + + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + + m_pDataLength = keeplen; + m_pData = keepdata; + m_ptrMBR = keepmbr; + m_pIdentifier = keepid; + m_children = lKeep; + m_totalDataLength = 0; + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) m_totalDataLength += m_pDataLength[u32Child]; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t u32Child = 0; u32Child < m_children; ++u32Child) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[u32Child]->m_pLow[cDim]); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[u32Child]->m_pHigh[cDim]); + } + } + + m_pTree->writeNode(this); + + // Divertion from R*-Tree algorithm here. First adjust + // the path to the root, then start reinserts, to avoid complicated handling + // of changes to the same node from multiple insertions. + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + m_pTree->insertData_impl( + reinsertlen[cIndex], reinsertdata[cIndex], + *(reinsertmbr[cIndex]), reinsertid[cIndex], + m_level, overflowTable); + } + + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + + return true; + } + else + { + NodePtr n; + NodePtr nn; + split(dataLength, pData, mbr, id, n, nn); + + if (pathBuffer.empty()) + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = -1; + nn->m_identifier = -1; + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + NodePtr ptrR = m_pTree->m_indexPool.acquire(); + if (ptrR.get() == 0) + { + ptrR = NodePtr(new Index(m_pTree, m_pTree->m_rootID, m_level + 1), &(m_pTree->m_indexPool)); + } + else + { + //ptrR->m_pTree = m_pTree; + ptrR->m_identifier = m_pTree->m_rootID; + ptrR->m_level = m_level + 1; + ptrR->m_nodeMBR = m_pTree->m_infiniteRegion; + } + + ptrR->insertEntry(0, 0, n->m_nodeMBR, n->m_identifier); + ptrR->insertEntry(0, 0, nn->m_nodeMBR, nn->m_identifier); + + m_pTree->writeNode(ptrR.get()); + + m_pTree->m_stats.m_nodesInLevel[m_level] = 2; + m_pTree->m_stats.m_nodesInLevel.push_back(1); + m_pTree->m_stats.m_u32TreeHeight = m_level + 2; + } + else + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = m_identifier; + nn->m_identifier = -1; + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(n.get(), nn.get(), pathBuffer, overflowTable); + } + + return true; + } +} + +void Node::reinsertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep) +{ + ReinsertEntry** v = new ReinsertEntry*[m_capacity + 1]; + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + PointPtr nc = m_pTree->m_pointPool.acquire(); + m_nodeMBR.getCenter(*nc); + PointPtr c = m_pTree->m_pointPool.acquire(); + + for (uint32_t u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + try + { + v[u32Child] = new ReinsertEntry(u32Child, 0.0); + } + catch (...) + { + for (uint32_t i = 0; i < u32Child; ++i) delete v[i]; + delete[] v; + throw; + } + + m_ptrMBR[u32Child]->getCenter(*c); + + // calculate relative distance of every entry from the node MBR (ignore square root.) + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + double d = nc->m_pCoords[cDim] - c->m_pCoords[cDim]; + v[u32Child]->m_dist += d * d; + } + } + + // sort by increasing order of distances. + ::qsort(v, m_capacity + 1, sizeof(ReinsertEntry*), ReinsertEntry::compareReinsertEntry); + + uint32_t cReinsert = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_reinsertFactor)); + + uint32_t cCount; + + for (cCount = 0; cCount < cReinsert; ++cCount) + { + reinsert.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + for (cCount = cReinsert; cCount < m_capacity + 1; ++cCount) + { + keep.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + delete[] v; +} + +void Node::rtreeSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + uint32_t u32Child; + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + // use this mask array for marking visited entries. + byte* mask = new byte[m_capacity + 1]; + bzero(mask, m_capacity + 1); + + // insert new data in the node for easier manipulation. Data arrays are always + // by one larger than node capacity. + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + // m_totalDataLength does not need to be increased here. + + // initialize each group with the seed entries. + uint32_t seed1, seed2; + pickSeeds(seed1, seed2); + + group1.push_back(seed1); + group2.push_back(seed2); + + mask[seed1] = 1; + mask[seed2] = 1; + + // find MBR of each group. + RegionPtr mbr1 = m_pTree->m_regionPool.acquire(); + *mbr1 = *(m_ptrMBR[seed1]); + RegionPtr mbr2 = m_pTree->m_regionPool.acquire(); + *mbr2 = *(m_ptrMBR[seed2]); + + // count how many entries are left unchecked (exclude the seeds here.) + uint32_t cRemaining = m_capacity + 1 - 2; + + while (cRemaining > 0) + { + if (minimumLoad - group1.size() == cRemaining) + { + // all remaining entries must be assigned to group1 to comply with minimun load requirement. + for (u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + if (mask[u32Child] == 0) + { + group1.push_back(u32Child); + mask[u32Child] = 1; + --cRemaining; + } + } + } + else if (minimumLoad - group2.size() == cRemaining) + { + // all remaining entries must be assigned to group2 to comply with minimun load requirement. + for (u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + if (mask[u32Child] == 0) + { + group2.push_back(u32Child); + mask[u32Child] = 1; + --cRemaining; + } + } + } + else + { + // For all remaining entries compute the difference of the cost of grouping an + // entry in either group. When done, choose the entry that yielded the maximum + // difference. In case of linear split, select any entry (e.g. the first one.) + uint32_t sel; + double md1 = 0.0, md2 = 0.0; + double m = -std::numeric_limits<double>::max(); + double d1, d2, d; + double a1 = mbr1->getArea(); + double a2 = mbr2->getArea(); + + RegionPtr a = m_pTree->m_regionPool.acquire(); + RegionPtr b = m_pTree->m_regionPool.acquire(); + + for (u32Child = 0; u32Child < m_capacity + 1; ++u32Child) + { + if (mask[u32Child] == 0) + { + mbr1->getCombinedRegion(*a, *(m_ptrMBR[u32Child])); + d1 = a->getArea() - a1; + mbr2->getCombinedRegion(*b, *(m_ptrMBR[u32Child])); + d2 = b->getArea() - a2; + d = std::abs(d1 - d2); + + if (d > m) + { + m = d; + md1 = d1; md2 = d2; + sel = u32Child; + if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break; + } + } + } + + // determine the group where we should add the new entry. + int32_t group = -1; + + if (md1 < md2) + { + group1.push_back(sel); + group = 1; + } + else if (md2 < md1) + { + group2.push_back(sel); + group = 2; + } + else if (a1 < a2) + { + group1.push_back(sel); + group = 1; + } + else if (a2 < a1) + { + group2.push_back(sel); + group = 2; + } + else if (group1.size() < group2.size()) + { + group1.push_back(sel); + group = 1; + } + else if (group2.size() < group1.size()) + { + group2.push_back(sel); + group = 2; + } + else + { + group1.push_back(sel); + group = 1; + } + mask[sel] = 1; + --cRemaining; + if (group == 1) + { + mbr1->combineRegion(*(m_ptrMBR[sel])); + } + else + { + mbr2->combineRegion(*(m_ptrMBR[sel])); + } + } + } + + delete[] mask; +} + +void Node::rstarSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + RstarSplitEntry** dataLow = 0; + RstarSplitEntry** dataHigh = 0; + + try + { + dataLow = new RstarSplitEntry*[m_capacity + 1]; + dataHigh = new RstarSplitEntry*[m_capacity + 1]; + } + catch (...) + { + delete[] dataLow; + throw; + } + + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + // m_totalDataLength does not need to be increased here. + + uint32_t nodeSPF = static_cast<uint32_t>( + std::floor((m_capacity + 1) * m_pTree->m_splitDistributionFactor)); + uint32_t splitDistribution = (m_capacity + 1) - (2 * nodeSPF) + 2; + + uint32_t u32Child = 0, cDim, cIndex; + + for (u32Child = 0; u32Child <= m_capacity; ++u32Child) + { + try + { + dataLow[u32Child] = new RstarSplitEntry(m_ptrMBR[u32Child].get(), u32Child, 0); + } + catch (...) + { + for (uint32_t i = 0; i < u32Child; ++i) delete dataLow[i]; + delete[] dataLow; + delete[] dataHigh; + throw; + } + + dataHigh[u32Child] = dataLow[u32Child]; + } + + double minimumMargin = std::numeric_limits<double>::max(); + uint32_t splitAxis = std::numeric_limits<uint32_t>::max(); + uint32_t sortOrder = std::numeric_limits<uint32_t>::max(); + + // chooseSplitAxis. + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow); + ::qsort(dataHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh); + + // calculate sum of margins and overlap for all distributions. + double marginl = 0.0; + double marginh = 0.0; + + Region bbl1, bbl2, bbh1, bbh2; + + for (u32Child = 1; u32Child <= splitDistribution; ++u32Child) + { + uint32_t l = nodeSPF - 1 + u32Child; + + bbl1 = *(dataLow[0]->m_pRegion); + bbh1 = *(dataHigh[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bbl1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh1.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + bbl2 = *(dataLow[l]->m_pRegion); + bbh2 = *(dataHigh[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bbl2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + bbh2.combineRegion(*(dataHigh[cIndex]->m_pRegion)); + } + + marginl += bbl1.getMargin() + bbl2.getMargin(); + marginh += bbh1.getMargin() + bbh2.getMargin(); + } // for (u32Child) + + double margin = std::min(marginl, marginh); + + // keep minimum margin as split axis. + if (margin < minimumMargin) + { + minimumMargin = margin; + splitAxis = cDim; + sortOrder = (marginl < marginh) ? 0 : 1; + } + + // increase the dimension according to which the data entries should be sorted. + for (u32Child = 0; u32Child <= m_capacity; ++u32Child) + { + dataLow[u32Child]->m_sortDim = cDim + 1; + } + } // for (cDim) + + for (u32Child = 0; u32Child <= m_capacity; ++u32Child) + { + dataLow[u32Child]->m_sortDim = splitAxis; + } + + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), (sortOrder == 0) ? RstarSplitEntry::compareLow : RstarSplitEntry::compareHigh); + + double ma = std::numeric_limits<double>::max(); + double mo = std::numeric_limits<double>::max(); + uint32_t splitPoint = std::numeric_limits<uint32_t>::max(); + + Region bb1, bb2; + + for (u32Child = 1; u32Child <= splitDistribution; ++u32Child) + { + uint32_t l = nodeSPF - 1 + u32Child; + + bb1 = *(dataLow[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bb1.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + bb2 = *(dataLow[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bb2.combineRegion(*(dataLow[cIndex]->m_pRegion)); + } + + double o = bb1.getIntersectingArea(bb2); + + if (o < mo) + { + splitPoint = u32Child; + mo = o; + ma = bb1.getArea() + bb2.getArea(); + } + else if (o == mo) + { + double a = bb1.getArea() + bb2.getArea(); + + if (a < ma) + { + splitPoint = u32Child; + ma = a; + } + } + } // for (u32Child) + + uint32_t l1 = nodeSPF - 1 + splitPoint; + + for (cIndex = 0; cIndex < l1; ++cIndex) + { + group1.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + for (cIndex = l1; cIndex <= m_capacity; ++cIndex) + { + group2.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + delete[] dataLow; + delete[] dataHigh; +} + +void Node::pickSeeds(uint32_t& index1, uint32_t& index2) +{ + double separation = -std::numeric_limits<double>::max(); + double inefficiency = -std::numeric_limits<double>::max(); + uint32_t cDim, u32Child, cIndex; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_RSTAR: + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + double leastLower = m_ptrMBR[0]->m_pLow[cDim]; + double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim]; + uint32_t greatestLower = 0; + uint32_t leastUpper = 0; + double width; + + for (u32Child = 1; u32Child <= m_capacity; ++u32Child) + { + if (m_ptrMBR[u32Child]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = u32Child; + if (m_ptrMBR[u32Child]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = u32Child; + + leastLower = std::min(m_ptrMBR[u32Child]->m_pLow[cDim], leastLower); + greatestUpper = std::max(m_ptrMBR[u32Child]->m_pHigh[cDim], greatestUpper); + } + + width = greatestUpper - leastLower; + if (width <= 0) width = 1; + + double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width; + + if (f > separation) + { + index1 = leastUpper; + index2 = greatestLower; + separation = f; + } + } // for (cDim) + + if (index1 == index2) + { + if (index2 == 0) ++index2; + else --index2; + } + + break; + case RV_QUADRATIC: + // for each pair of Regions (account for overflow Region too!) + for (u32Child = 0; u32Child < m_capacity; ++u32Child) + { + double a = m_ptrMBR[u32Child]->getArea(); + + for (cIndex = u32Child + 1; cIndex <= m_capacity; ++cIndex) + { + // get the combined MBR of those two entries. + Region r; + m_ptrMBR[u32Child]->getCombinedRegion(r, *(m_ptrMBR[cIndex])); + + // find the inefficiency of grouping these entries together. + double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea(); + + if (d > inefficiency) + { + inefficiency = d; + index1 = u32Child; + index2 = cIndex; + } + } // for (cIndex) + } // for (u32Child) + + break; + default: + throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported."); + } +} + +void Node::condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis) +{ + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + if (pathBuffer.empty()) + { + // eliminate root if it has only one child. + if (m_level != 0 && m_children == 1) + { + NodePtr ptrN = m_pTree->readNode(m_pIdentifier[0]); + m_pTree->deleteNode(ptrN.get()); + ptrN->m_identifier = m_pTree->m_rootID; + m_pTree->writeNode(ptrN.get()); + + m_pTree->m_stats.m_nodesInLevel.pop_back(); + m_pTree->m_stats.m_u32TreeHeight -= 1; + // HACK: pending deleteNode for deleted child will decrease nodesInLevel, later on. + m_pTree->m_stats.m_nodesInLevel[m_pTree->m_stats.m_u32TreeHeight - 1] = 2; + } + } + else + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrParent = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrParent.get()); + + // find the entry in the parent, that points to this node. + uint32_t child; + + for (child = 0; child != p->m_children; ++child) + { + if (p->m_pIdentifier[child] == m_identifier) break; + } + + if (m_children < minimumLoad) + { + // used space less than the minimum + // 1. eliminate node entry from the parent. deleteEntry will fix the parent's MBR. + p->deleteEntry(child); + // 2. add this node to the stack in order to reinsert its entries. + toReinsert.push(ptrThis); + } + else + { + // adjust the entry in 'p' to contain the new bounding region of this node. + *(p->m_ptrMBR[child]) = m_nodeMBR; + + // global recalculation necessary since the MBR can only shrink in size, + // due to data removal. + if (m_pTree->m_bTightMBRs) + { + for (uint32_t cDim = 0; cDim < p->m_nodeMBR.m_dimension; ++cDim) + { + p->m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t u32Child = 0; u32Child < p->m_children; ++u32Child) + { + p->m_nodeMBR.m_pLow[cDim] = std::min(p->m_nodeMBR.m_pLow[cDim], p->m_ptrMBR[u32Child]->m_pLow[cDim]); + p->m_nodeMBR.m_pHigh[cDim] = std::max(p->m_nodeMBR.m_pHigh[cDim], p->m_ptrMBR[u32Child]->m_pHigh[cDim]); + } + } + } + } + + // write parent node back to storage. + m_pTree->writeNode(p); + + p->condenseTree(toReinsert, pathBuffer, ptrParent); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Node.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/Node.h new file mode 100644 index 000000000..89e55945d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Node.h @@ -0,0 +1,188 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class RTree; + class Leaf; + class Index; + class Node; + + typedef Tools::PoolPointer<Node> NodePtr; + + class Node : public SpatialIndex::INode + { + public: + virtual ~Node(); + + // + // Tools::IObject interface + // + virtual Tools::IObject* clone(); + + // + // Tools::ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // SpatialIndex::IEntry interface + // + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + + // + // SpatialIndex::INode interface + // + virtual uint32_t getChildrenCount() const; + virtual id_type getChildIdentifier(uint32_t index) const; + virtual void getChildShape(uint32_t index, IShape** out) const; + virtual void getChildData(uint32_t index, uint32_t& length, byte** data) const; + virtual uint32_t getLevel() const; + virtual bool isIndex() const; + virtual bool isLeaf() const; + + private: + Node(); + Node(RTree* pTree, id_type id, uint32_t level, uint32_t capacity); + + virtual Node& operator=(const Node&); + + virtual void insertEntry(uint32_t dataLength, byte* pData, Region& mbr, id_type id); + virtual void deleteEntry(uint32_t index); + + virtual bool insertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable); + virtual void reinsertData(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep); + + virtual void rtreeSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2); + virtual void rstarSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2); + + virtual void pickSeeds(uint32_t& index1, uint32_t& index2); + + virtual void condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis); + + virtual NodePtr chooseSubtree(const Region& mbr, uint32_t level, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findLeaf(const Region& mbr, id_type id, std::stack<id_type>& pathBuffer) = 0; + + virtual void split(uint32_t dataLength, byte* pData, Region& mbr, id_type id, NodePtr& left, NodePtr& right) = 0; + + RTree* m_pTree; + // Parent of all nodes. + + uint32_t m_level; + // The level of the node in the tree. + // Leaves are always at level 0. + + id_type m_identifier; + // The unique ID of this node. + + uint32_t m_children; + // The number of children pointed by this node. + + uint32_t m_capacity; + // Specifies the node capacity. + + Region m_nodeMBR; + // The minimum bounding region enclosing all data contained in the node. + + byte** m_pData; + // The data stored in the node. + + RegionPtr* m_ptrMBR; + // The corresponding data MBRs. + + id_type* m_pIdentifier; + // The corresponding data identifiers. + + uint32_t* m_pDataLength; + + uint32_t m_totalDataLength; + + class RstarSplitEntry + { + public: + Region* m_pRegion; + uint32_t m_index; + uint32_t m_sortDim; + + RstarSplitEntry(Region* pr, uint32_t index, uint32_t dimension) : + m_pRegion(pr), m_index(index), m_sortDim(dimension) {} + + static int compareLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + assert(pe1->m_sortDim == pe2->m_sortDim); + + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] < pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] > pe2->m_pRegion->m_pLow[pe2->m_sortDim]) return 1; + return 0; + } + + static int compareHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + assert(pe1->m_sortDim == pe2->m_sortDim); + + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pHigh[pe2->m_sortDim]) return 1; + return 0; + } + }; // RstarSplitEntry + + class ReinsertEntry + { + public: + uint32_t m_index; + double m_dist; + + ReinsertEntry(uint32_t index, double dist) : m_index(index), m_dist(dist) {} + + static int compareReinsertEntry(const void* pv1, const void* pv2) + { + ReinsertEntry* pe1 = * (ReinsertEntry**) pv1; + ReinsertEntry* pe2 = * (ReinsertEntry**) pv2; + + if (pe1->m_dist < pe2->m_dist) return -1; + if (pe1->m_dist > pe2->m_dist) return 1; + return 0; + } + }; // ReinsertEntry + + // Needed to access protected members without having to cast from Node. + // It is more efficient than using member functions to access protected members. + friend class RTree; + friend class Leaf; + friend class Index; + friend class Tools::PointerPool<Node>; + friend class BulkLoader; + }; // Node + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/PointerPoolNode.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/PointerPoolNode.h new file mode 100644 index 000000000..e6977a0c9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/PointerPoolNode.h @@ -0,0 +1,138 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#ifndef __spatialindex_rtree_pointer_pool_node_h +#define __spatialindex_rtree_pointer_pool_node_h + +#include "Node.h" + +namespace Tools +{ + template<> class PointerPool<RTree::Node> + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + RTree::Node* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<RTree::Node> acquire() + { + if (! m_pool.empty()) + { + RTree::Node* p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + ++m_hits; + #endif + + return PoolPointer<RTree::Node>(p, this); + } + #ifndef NDEBUG + else + { + // fixme: well sort of... + ++m_pointerCount; + ++m_misses; + } + #endif + + return PoolPointer<RTree::Node>(); + } + + void release(RTree::Node* p) + { + if (p != 0) + { + if (m_pool.size() < m_capacity) + { + if (p->m_pData != 0) + { + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + // there is no need to set the pointer to zero, after deleting it, + // since it will be redeleted only if it is actually initialized again, + // a fact that will be depicted by variable m_children. + if (p->m_pData[cChild] != 0) delete[] p->m_pData[cChild]; + } + } + + p->m_level = 0; + p->m_identifier = -1; + p->m_children = 0; + p->m_totalDataLength = 0; + + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + protected: + uint32_t m_capacity; + std::stack<RTree::Node*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + +#endif /* __spatialindex_rtree_pointer_pool_node_h */ diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/RTree.cc b/sci-libs/libspatialindex/svn/trunk/src/rtree/RTree.cc new file mode 100644 index 000000000..dd5f23c45 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/RTree.cc @@ -0,0 +1,1551 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" +#include "BulkLoader.h" +#include "RTree.h" + +using namespace SpatialIndex::RTree; + +SpatialIndex::RTree::Data::Data(uint32_t len, byte* pData, Region& r, id_type id) + : m_id(id), m_region(r), m_pData(0), m_dataLength(len) +{ + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, pData, m_dataLength); + } +} + +SpatialIndex::RTree::Data::~Data() +{ + delete[] m_pData; +} + +SpatialIndex::RTree::Data* SpatialIndex::RTree::Data::clone() +{ + return new Data(m_dataLength, m_pData, m_region, m_id); +} + +id_type SpatialIndex::RTree::Data::getIdentifier() const +{ + return m_id; +} + +void SpatialIndex::RTree::Data::getShape(IShape** out) const +{ + *out = new Region(m_region); +} + +void SpatialIndex::RTree::Data::getData(uint32_t& len, byte** data) const +{ + len = m_dataLength; + *data = 0; + + if (m_dataLength > 0) + { + *data = new byte[m_dataLength]; + memcpy(*data, m_pData, m_dataLength); + } +} + +uint32_t SpatialIndex::RTree::Data::getByteArraySize() +{ + return + sizeof(id_type) + + sizeof(uint32_t) + + m_dataLength + + m_region.getByteArraySize(); +} + +void SpatialIndex::RTree::Data::loadFromByteArray(const byte* ptr) +{ + memcpy(&m_id, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + delete[] m_pData; + m_pData = 0; + + memcpy(&m_dataLength, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, ptr, m_dataLength); + ptr += m_dataLength; + } + + m_region.loadFromByteArray(ptr); +} + +void SpatialIndex::RTree::Data::storeToByteArray(byte** data, uint32_t& len) +{ + // it is thread safe this way. + uint32_t regionsize; + byte* regiondata = 0; + m_region.storeToByteArray(®iondata, regionsize); + + len = sizeof(id_type) + sizeof(uint32_t) + m_dataLength + regionsize; + + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_id, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_dataLength, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + memcpy(ptr, m_pData, m_dataLength); + ptr += m_dataLength; + } + + memcpy(ptr, regiondata, regionsize); + delete[] regiondata; + // ptr += regionsize; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::returnRTree(SpatialIndex::IStorageManager& sm, Tools::PropertySet& ps) +{ + SpatialIndex::ISpatialIndex* si = new SpatialIndex::RTree::RTree(sm, ps); + return si; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::createNewRTree( + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + RTreeVariant rv, + id_type& indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = fillFactor; + ps.setProperty("FillFactor", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = indexCapacity; + ps.setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = leafCapacity; + ps.setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = dimension; + ps.setProperty("Dimension", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = rv; + ps.setProperty("TreeVariant", var); + + ISpatialIndex* ret = returnRTree(sm, ps); + + var.m_varType = Tools::VT_LONGLONG; + var = ps.getProperty("IndexIdentifier"); + indexIdentifier = var.m_val.llVal; + + return ret; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + SpatialIndex::RTree::RTreeVariant rv, + id_type& indexIdentifier) +{ + SpatialIndex::ISpatialIndex* tree = createNewRTree(sm, fillFactor, indexCapacity, leafCapacity, dimension, rv, indexIdentifier); + + uint32_t bindex = static_cast<uint32_t>(std::floor(static_cast<double>(indexCapacity * fillFactor))); + uint32_t bleaf = static_cast<uint32_t>(std::floor(static_cast<double>(leafCapacity * fillFactor))); + + SpatialIndex::RTree::BulkLoader bl; + + switch (m) + { + case BLM_STR: + bl.bulkLoadUsingSTR(static_cast<RTree*>(tree), stream, bindex, bleaf, 10000, 100); + break; + default: + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Unknown bulk load method."); + break; + } + + return tree; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::createAndBulkLoadNewRTree( + BulkLoadMethod m, + IDataStream& stream, + SpatialIndex::IStorageManager& sm, + Tools::PropertySet& ps, + id_type& indexIdentifier) +{ + Tools::Variant var; + RTreeVariant rv; + double fillFactor; + uint32_t indexCapacity, leafCapacity, dimension, pageSize, numberOfPages; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != RV_LINEAR && + var.m_val.lVal != RV_QUADRATIC && + var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property TreeVariant must be Tools::VT_LONG and of RTreeVariant type"); + + rv = static_cast<RTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property FillFactor was not of type Tools::VT_DOUBLE"); + + if (var.m_val.dblVal <= 0.0) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property FillFactor was less than 0.0"); + + if (((rv == RV_LINEAR || rv == RV_QUADRATIC) && var.m_val.dblVal > 0.5)) + throw Tools::IllegalArgumentException( "createAndBulkLoadNewRTree: Property FillFactor must be in range (0.0, 0.5) for LINEAR or QUADRATIC index types"); + if ( var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property FillFactor must be in range (0.0, 1.0) for RSTAR index type"); + fillFactor = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property IndexCapacity must be Tools::VT_ULONG and >= 4"); + + indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property LeafCapacity must be Tools::VT_ULONG and >= 4"); + + leafCapacity = var.m_val.ulVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property Dimension must be greater than 1"); + + dimension = var.m_val.ulVal; + } + + // page size + var = ps.getProperty("ExternalSortBufferPageSize"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferPageSize must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferPageSize must be greater than 1"); + + pageSize = var.m_val.ulVal; + } + + // number of pages + var = ps.getProperty("ExternalSortBufferTotalPages"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferTotalPages must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Property ExternalSortBufferTotalPages must be greater than 1"); + + numberOfPages = var.m_val.ulVal; + } + + SpatialIndex::ISpatialIndex* tree = createNewRTree(sm, fillFactor, indexCapacity, leafCapacity, dimension, rv, indexIdentifier); + + uint32_t bindex = static_cast<uint32_t>(std::floor(static_cast<double>(indexCapacity * fillFactor))); + uint32_t bleaf = static_cast<uint32_t>(std::floor(static_cast<double>(leafCapacity * fillFactor))); + + SpatialIndex::RTree::BulkLoader bl; + + switch (m) + { + case BLM_STR: + bl.bulkLoadUsingSTR(static_cast<RTree*>(tree), stream, bindex, bleaf, pageSize, numberOfPages); + break; + default: + throw Tools::IllegalArgumentException("createAndBulkLoadNewRTree: Unknown bulk load method."); + break; + } + + return tree; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::RTree::loadRTree(IStorageManager& sm, id_type indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = indexIdentifier; + ps.setProperty("IndexIdentifier", var); + + return returnRTree(sm, ps); +} + +SpatialIndex::RTree::RTree::RTree(IStorageManager& sm, Tools::PropertySet& ps) : + m_pStorageManager(&sm), + m_rootID(StorageManager::NewPage), + m_headerID(StorageManager::NewPage), + m_treeVariant(RV_RSTAR), + m_fillFactor(0.7), + m_indexCapacity(100), + m_leafCapacity(100), + m_nearMinimumOverlapFactor(32), + m_splitDistributionFactor(0.4), + m_reinsertFactor(0.3), + m_dimension(2), + m_bTightMBRs(true), + m_pointPool(500), + m_regionPool(1000), + m_indexPool(100), + m_leafPool(100) +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + + Tools::Variant var = ps.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType == Tools::VT_LONGLONG) m_headerID = var.m_val.llVal; + else if (var.m_varType == Tools::VT_LONG) m_headerID = var.m_val.lVal; + // for backward compatibility only. + else throw Tools::IllegalArgumentException("RTree: Property IndexIdentifier must be Tools::VT_LONGLONG"); + + initOld(ps); + } + else + { + initNew(ps); + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = m_headerID; + ps.setProperty("IndexIdentifier", var); + } +} + +SpatialIndex::RTree::RTree::~RTree() +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_destroy(&m_rwLock); +#endif + + storeHeader(); +} + +// +// ISpatialIndex interface +// + +void SpatialIndex::RTree::RTree::insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("insertData: cannot acquire an exclusive lock"); +#endif + + try + { + // convert the shape into a Region (R-Trees index regions only; i.e., approximations of the shapes). + RegionPtr mbr = m_regionPool.acquire(); + shape.getMBR(*mbr); + + byte* buffer = 0; + + if (len > 0) + { + buffer = new byte[len]; + memcpy(buffer, pData, len); + } + + insertData_impl(len, buffer, *mbr, id); + // the buffer is stored in the tree. Do not delete here. + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +bool SpatialIndex::RTree::RTree::deleteData(const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("deleteData: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("deleteData: cannot acquire an exclusive lock"); +#endif + + try + { + RegionPtr mbr = m_regionPool.acquire(); + shape.getMBR(*mbr); + bool ret = deleteData_impl(*mbr, id); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + return ret; + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::containsWhatQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("containsWhatQuery: Shape has the wrong number of dimensions."); + rangeQuery(ContainmentQuery, query, v); +} + +void SpatialIndex::RTree::RTree::intersectsWithQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("intersectsWithQuery: Shape has the wrong number of dimensions."); + rangeQuery(IntersectionQuery, query, v); +} + +void SpatialIndex::RTree::RTree::pointLocationQuery(const Point& query, IVisitor& v) +{ + if (query.m_dimension != m_dimension) throw Tools::IllegalArgumentException("pointLocationQuery: Shape has the wrong number of dimensions."); + Region r(query, query); + rangeQuery(IntersectionQuery, r, v); +} + +void SpatialIndex::RTree::RTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("nearestNeighborQuery: cannot acquire a shared lock"); +#endif + + try + { + std::priority_queue<NNEntry*, std::vector<NNEntry*>, NNEntry::ascending> queue; + + queue.push(new NNEntry(m_rootID, 0, 0.0)); + + uint32_t count = 0; + double knearest = 0.0; + + while (! queue.empty()) + { + NNEntry* pFirst = queue.top(); + + // report all nearest neighbors with equal greatest distances. + // (neighbors can be more than k, if many happen to have the same greatest distance). + if (count >= k && pFirst->m_minDist > knearest) break; + + queue.pop(); + + if (pFirst->m_pEntry == 0) + { + // n is a leaf or an index. + NodePtr n = readNode(pFirst->m_id); + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (n->m_level == 0) + { + Data* e = new Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + // we need to compare the query with the actual data entry here, so we call the + // appropriate getMinimumDistance method of NearestNeighborComparator. + queue.push(new NNEntry(n->m_pIdentifier[cChild], e, nnc.getMinimumDistance(query, *e))); + } + else + { + queue.push(new NNEntry(n->m_pIdentifier[cChild], 0, nnc.getMinimumDistance(query, *(n->m_ptrMBR[cChild])))); + } + } + } + else + { + v.visitData(*(static_cast<IData*>(pFirst->m_pEntry))); + ++(m_stats.m_u64QueryResults); + ++count; + knearest = pFirst->m_minDist; + delete pFirst->m_pEntry; + } + + delete pFirst; + } + + while (! queue.empty()) + { + NNEntry* e = queue.top(); queue.pop(); + if (e->m_pEntry != 0) delete e->m_pEntry; + delete e; + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + NNComparator nnc; + nearestNeighborQuery(k, query, v, nnc); +} + + +void SpatialIndex::RTree::RTree::selfJoinQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) + throw Tools::IllegalArgumentException("selfJoinQuery: Shape has the wrong number of dimensions."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("selfJoinQuery: cannot acquire a shared lock"); +#endif + + try + { + RegionPtr mbr = m_regionPool.acquire(); + query.getMBR(*mbr); + selfJoinQuery(m_rootID, m_rootID, *mbr, v); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::queryStrategy(IQueryStrategy& qs) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("queryStrategy: cannot acquire a shared lock"); +#endif + + id_type next = m_rootID; + bool hasNext = true; + + try + { + while (hasNext) + { + NodePtr n = readNode(next); + qs.getNextEntry(*n, next, hasNext); + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::getIndexProperties(Tools::PropertySet& out) const +{ + Tools::Variant var; + + // dimension + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_dimension; + out.setProperty("Dimension", var); + + // index capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexCapacity; + out.setProperty("IndexCapacity", var); + + // leaf capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafCapacity; + out.setProperty("LeafCapacity", var); + + // R-tree variant + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = m_treeVariant; + out.setProperty("TreeVariant", var); + + // fill factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_fillFactor; + out.setProperty("FillFactor", var); + + // near minimum overlap factor + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_nearMinimumOverlapFactor; + out.setProperty("NearMinimumOverlapFactor", var); + + // split distribution factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_splitDistributionFactor; + out.setProperty("SplitDistributionFactor", var); + + // reinsert factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_reinsertFactor; + out.setProperty("ReinsertFactor", var); + + // tight MBRs + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = m_bTightMBRs; + out.setProperty("EnsureTightMBRs", var); + + // index pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexPool.getCapacity(); + out.setProperty("IndexPoolCapacity", var); + + // leaf pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafPool.getCapacity(); + out.setProperty("LeafPoolCapacity", var); + + // region pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_regionPool.getCapacity(); + out.setProperty("RegionPoolCapacity", var); + + // point pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_pointPool.getCapacity(); + out.setProperty("PointPoolCapacity", var); +} + +void SpatialIndex::RTree::RTree::addCommand(ICommand* pCommand, CommandType ct) +{ + switch (ct) + { + case CT_NODEREAD: + m_readNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEWRITE: + m_writeNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEDELETE: + m_deleteNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + } +} + +bool SpatialIndex::RTree::RTree::isIndexValid() +{ + bool ret = true; + std::stack<ValidateEntry> st; + NodePtr root = readNode(m_rootID); + + if (root->m_level != m_stats.m_u32TreeHeight - 1) + { + std::cerr << "Invalid tree height." << std::endl; + return false; + } + + std::map<uint32_t, uint32_t> nodesInLevel; + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(root->m_level, 1)); + + ValidateEntry e(root->m_nodeMBR, root); + st.push(e); + + while (! st.empty()) + { + e = st.top(); st.pop(); + + Region tmpRegion; + tmpRegion = m_infiniteRegion; + + for (uint32_t cDim = 0; cDim < tmpRegion.m_dimension; ++cDim) + { + tmpRegion.m_pLow[cDim] = std::numeric_limits<double>::max(); + tmpRegion.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + tmpRegion.m_pLow[cDim] = std::min(tmpRegion.m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pLow[cDim]); + tmpRegion.m_pHigh[cDim] = std::max(tmpRegion.m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pHigh[cDim]); + } + } + + if (! (tmpRegion == e.m_pNode->m_nodeMBR)) + { + std::cerr << "Invalid parent information." << std::endl; + ret = false; + } + else if (! (tmpRegion == e.m_parentMBR)) + { + std::cerr << "Error in parent." << std::endl; + ret = false; + } + + if (e.m_pNode->m_level != 0) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]); + ValidateEntry tmpEntry(*(e.m_pNode->m_ptrMBR[cChild]), ptrN); + + std::map<uint32_t, uint32_t>::iterator itNodes = nodesInLevel.find(tmpEntry.m_pNode->m_level); + + if (itNodes == nodesInLevel.end()) + { + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(tmpEntry.m_pNode->m_level, 1l)); + } + else + { + nodesInLevel[tmpEntry.m_pNode->m_level] = nodesInLevel[tmpEntry.m_pNode->m_level] + 1; + } + + st.push(tmpEntry); + } + } + } + + uint32_t nodes = 0; + for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel) + { + if (nodesInLevel[cLevel] != m_stats.m_nodesInLevel[cLevel]) + { + std::cerr << "Invalid nodesInLevel information." << std::endl; + ret = false; + } + + nodes += m_stats.m_nodesInLevel[cLevel]; + } + + if (nodes != m_stats.m_u32Nodes) + { + std::cerr << "Invalid number of nodes information." << std::endl; + ret = false; + } + + return ret; +} + +void SpatialIndex::RTree::RTree::getStatistics(IStatistics** out) const +{ + *out = new Statistics(m_stats); +} + +void SpatialIndex::RTree::RTree::initNew(Tools::PropertySet& ps) +{ + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != RV_LINEAR && + var.m_val.lVal != RV_QUADRATIC && + var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initNew: Property TreeVariant must be Tools::VT_LONG and of RTreeVariant type"); + + m_treeVariant = static_cast<RTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE) + throw Tools::IllegalArgumentException("initNew: Property FillFactor was not of type Tools::VT_DOUBLE"); + + if (var.m_val.dblVal <= 0.0) + throw Tools::IllegalArgumentException("initNew: Property FillFactor was less than 0.0"); + + if (((m_treeVariant == RV_LINEAR || m_treeVariant == RV_QUADRATIC) && var.m_val.dblVal > 0.5)) + throw Tools::IllegalArgumentException( "initNew: Property FillFactor must be in range " + "(0.0, 0.5) for LINEAR or QUADRATIC index types"); + if ( var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException( "initNew: Property FillFactor must be in range " + "(0.0, 1.0) for RSTAR index type"); + m_fillFactor = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property IndexCapacity must be Tools::VT_ULONG and >= 4"); + + m_indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property LeafCapacity must be Tools::VT_ULONG and >= 4"); + + m_leafCapacity = var.m_val.ulVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be greater than 1"); + + m_dimension = var.m_val.ulVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) + throw Tools::IllegalArgumentException("initNew: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); + + m_stats.m_u32TreeHeight = 1; + m_stats.m_nodesInLevel.push_back(0); + + Leaf root(this, -1); + m_rootID = writeNode(&root); + + storeHeader(); +} + +void SpatialIndex::RTree::RTree::initOld(Tools::PropertySet& ps) +{ + loadHeader(); + + // only some of the properties may be changed. + // the rest are just ignored. + + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != RV_LINEAR && + var.m_val.lVal != RV_QUADRATIC && + var.m_val.lVal != RV_RSTAR)) + throw Tools::IllegalArgumentException("initOld: Property TreeVariant must be Tools::VT_LONG and of RTreeVariant type"); + + m_treeVariant = static_cast<RTreeVariant>(var.m_val.lVal); + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initOld: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); +} + +void SpatialIndex::RTree::RTree::storeHeader() +{ + const uint32_t headerSize = + sizeof(id_type) + // m_rootID + sizeof(RTreeVariant) + // m_treeVariant + sizeof(double) + // m_fillFactor + sizeof(uint32_t) + // m_indexCapacity + sizeof(uint32_t) + // m_leafCapacity + sizeof(uint32_t) + // m_nearMinimumOverlapFactor + sizeof(double) + // m_splitDistributionFactor + sizeof(double) + // m_reinsertFactor + sizeof(uint32_t) + // m_dimension + sizeof(char) + // m_bTightMBRs + sizeof(uint32_t) + // m_stats.m_nodes + sizeof(uint64_t) + // m_stats.m_data + sizeof(uint32_t) + // m_stats.m_treeHeight + m_stats.m_u32TreeHeight * sizeof(uint32_t); // m_stats.m_nodesInLevel + + byte* header = new byte[headerSize]; + byte* ptr = header; + + memcpy(ptr, &m_rootID, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_treeVariant, sizeof(RTreeVariant)); + ptr += sizeof(RTreeVariant); + memcpy(ptr, &m_fillFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_indexCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_leafCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_nearMinimumOverlapFactor, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_splitDistributionFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_reinsertFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c = (char) m_bTightMBRs; + memcpy(ptr, &c, sizeof(char)); + ptr += sizeof(char); + memcpy(ptr, &(m_stats.m_u32Nodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_u64Data), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(ptr, &(m_stats.m_u32TreeHeight), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel) + { + memcpy(ptr, &(m_stats.m_nodesInLevel[cLevel]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + m_pStorageManager->storeByteArray(m_headerID, headerSize, header); + + delete[] header; +} + +void SpatialIndex::RTree::RTree::loadHeader() +{ + uint32_t headerSize; + byte* header = 0; + m_pStorageManager->loadByteArray(m_headerID, headerSize, &header); + + byte* ptr = header; + + memcpy(&m_rootID, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&m_treeVariant, ptr, sizeof(RTreeVariant)); + ptr += sizeof(RTreeVariant); + memcpy(&m_fillFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_indexCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_leafCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_nearMinimumOverlapFactor, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_splitDistributionFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_reinsertFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c; + memcpy(&c, ptr, sizeof(char)); + m_bTightMBRs = (c != 0); + ptr += sizeof(char); + memcpy(&(m_stats.m_u32Nodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_u64Data), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(&(m_stats.m_u32TreeHeight), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_u32TreeHeight; ++cLevel) + { + uint32_t cNodes; + memcpy(&cNodes, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + m_stats.m_nodesInLevel.push_back(cNodes); + } + + delete[] header; +} + +void SpatialIndex::RTree::RTree::insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id) +{ + assert(mbr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + byte* overflowTable = 0; + + try + { + NodePtr root = readNode(m_rootID); + + overflowTable = new byte[root->m_level]; + bzero(overflowTable, root->m_level); + + NodePtr l = root->chooseSubtree(mbr, 0, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mbr, id, pathBuffer, overflowTable); + + delete[] overflowTable; + ++(m_stats.m_u64Data); + } + catch (...) + { + delete[] overflowTable; + throw; + } +} + +void SpatialIndex::RTree::RTree::insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id, uint32_t level, byte* overflowTable) +{ + assert(mbr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_rootID); + NodePtr n = root->chooseSubtree(mbr, level, pathBuffer); + + assert(n->m_level == level); + + if (n.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + n->insertData(dataLength, pData, mbr, id, pathBuffer, overflowTable); +} + +bool SpatialIndex::RTree::RTree::deleteData_impl(const Region& mbr, id_type id) +{ + assert(mbr.m_dimension == m_dimension); + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_rootID); + NodePtr l = root->findLeaf(mbr, id, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + + if (l.get() != 0) + { + Leaf* pL = static_cast<Leaf*>(l.get()); + pL->deleteData(id, pathBuffer); + --(m_stats.m_u64Data); + return true; + } + + return false; +} + +SpatialIndex::id_type SpatialIndex::RTree::RTree::writeNode(Node* n) +{ + byte* buffer; + uint32_t dataLength; + n->storeToByteArray(&buffer, dataLength); + + id_type page; + if (n->m_identifier < 0) page = StorageManager::NewPage; + else page = n->m_identifier; + + try + { + m_pStorageManager->storeByteArray(page, dataLength, buffer); + delete[] buffer; + } + catch (InvalidPageException& e) + { + delete[] buffer; + std::cerr << e.what() << std::endl; + throw; + } + + if (n->m_identifier < 0) + { + n->m_identifier = page; + ++(m_stats.m_u32Nodes); + +#ifndef NDEBUG + try + { + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel.at(n->m_level) + 1; + } + catch(...) + { + throw Tools::IllegalStateException("writeNode: writing past the end of m_nodesInLevel."); + } +#else + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] + 1; +#endif + } + + ++(m_stats.m_u64Writes); + + for (size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex) + { + m_writeNodeCommands[cIndex]->execute(*n); + } + + return page; +} + +SpatialIndex::RTree::NodePtr SpatialIndex::RTree::RTree::readNode(id_type page) +{ + uint32_t dataLength; + byte* buffer; + + try + { + m_pStorageManager->loadByteArray(page, dataLength, &buffer); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + throw; + } + + try + { + uint32_t nodeType; + memcpy(&nodeType, buffer, sizeof(uint32_t)); + + NodePtr n; + + if (nodeType == PersistentIndex) n = m_indexPool.acquire(); + else if (nodeType == PersistentLeaf) n = m_leafPool.acquire(); + else throw Tools::IllegalStateException("readNode: failed reading the correct node type information"); + + if (n.get() == 0) + { + if (nodeType == PersistentIndex) n = NodePtr(new Index(this, -1, 0), &m_indexPool); + else if (nodeType == PersistentLeaf) n = NodePtr(new Leaf(this, -1), &m_leafPool); + } + + //n->m_pTree = this; + n->m_identifier = page; + n->loadFromByteArray(buffer); + + ++(m_stats.m_u64Reads); + + for (size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex) + { + m_readNodeCommands[cIndex]->execute(*n); + } + + delete[] buffer; + return n; + } + catch (...) + { + delete[] buffer; + throw; + } +} + +void SpatialIndex::RTree::RTree::deleteNode(Node* n) +{ + try + { + m_pStorageManager->deleteByteArray(n->m_identifier); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + throw; + } + + --(m_stats.m_u32Nodes); + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] - 1; + + for (size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex) + { + m_deleteNodeCommands[cIndex]->execute(*n); + } +} + +void SpatialIndex::RTree::RTree::rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("rangeQuery: cannot acquire a shared lock"); +#endif + + try + { + std::stack<NodePtr> st; + NodePtr root = readNode(m_rootID); + + if (root->m_children > 0 && query.intersectsShape(root->m_nodeMBR)) st.push(root); + + while (! st.empty()) + { + NodePtr n = st.top(); st.pop(); + + if (n->m_level == 0) + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + bool b; + if (type == ContainmentQuery) b = query.containsShape(*(n->m_ptrMBR[cChild])); + else b = query.intersectsShape(*(n->m_ptrMBR[cChild])); + + if (b) + { + Data data = Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + v.visitData(data); + ++(m_stats.m_u64QueryResults); + } + } + } + else + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (query.intersectsShape(*(n->m_ptrMBR[cChild]))) st.push(readNode(n->m_pIdentifier[cChild])); + } + } + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::RTree::RTree::selfJoinQuery(id_type id1, id_type id2, const Region& r, IVisitor& vis) +{ + NodePtr n1 = readNode(id1); + NodePtr n2 = readNode(id2); + vis.visitNode(*n1); + vis.visitNode(*n2); + + for (uint32_t cChild1 = 0; cChild1 < n1->m_children; ++cChild1) + { + if (r.intersectsRegion(*(n1->m_ptrMBR[cChild1]))) + { + for (uint32_t cChild2 = 0; cChild2 < n2->m_children; ++cChild2) + { + if ( + r.intersectsRegion(*(n2->m_ptrMBR[cChild2])) && + n1->m_ptrMBR[cChild1]->intersectsRegion(*(n2->m_ptrMBR[cChild2]))) + { + if (n1->m_level == 0) + { + if (n1->m_pIdentifier[cChild1] != n2->m_pIdentifier[cChild2]) + { + assert(n2->m_level == 0); + + std::vector<const IData*> v; + Data e1(n1->m_pDataLength[cChild1], n1->m_pData[cChild1], *(n1->m_ptrMBR[cChild1]), n1->m_pIdentifier[cChild1]); + Data e2(n2->m_pDataLength[cChild2], n2->m_pData[cChild2], *(n2->m_ptrMBR[cChild2]), n2->m_pIdentifier[cChild2]); + v.push_back(&e1); + v.push_back(&e2); + vis.visitData(v); + } + } + else + { + Region rr = r.getIntersectingRegion(n1->m_ptrMBR[cChild1]->getIntersectingRegion(*(n2->m_ptrMBR[cChild2]))); + selfJoinQuery(n1->m_pIdentifier[cChild1], n2->m_pIdentifier[cChild2], rr, vis); + } + } + } + } + } +} + +std::ostream& SpatialIndex::RTree::operator<<(std::ostream& os, const RTree& t) +{ + os << "Dimension: " << t.m_dimension << std::endl + << "Fill factor: " << t.m_fillFactor << std::endl + << "Index capacity: " << t.m_indexCapacity << std::endl + << "Leaf capacity: " << t.m_leafCapacity << std::endl + << "Tight MBRs: " << ((t.m_bTightMBRs) ? "enabled" : "disabled") << std::endl; + + if (t.m_treeVariant == RV_RSTAR) + { + os << "Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl + << "Reinsert factor: " << t.m_reinsertFactor << std::endl + << "Split distribution factor: " << t.m_splitDistributionFactor << std::endl; + } + + if (t.m_stats.getNumberOfNodesInLevel(0) > 0) + os << "Utilization: " << 100 * t.m_stats.getNumberOfData() / (t.m_stats.getNumberOfNodesInLevel(0) * t.m_leafCapacity) << "%" << std::endl + << t.m_stats; + + #ifndef NDEBUG + os << "Leaf pool hits: " << t.m_leafPool.m_hits << std::endl + << "Leaf pool misses: " << t.m_leafPool.m_misses << std::endl + << "Index pool hits: " << t.m_indexPool.m_hits << std::endl + << "Index pool misses: " << t.m_indexPool.m_misses << std::endl + << "Region pool hits: " << t.m_regionPool.m_hits << std::endl + << "Region pool misses: " << t.m_regionPool.m_misses << std::endl + << "Point pool hits: " << t.m_pointPool.m_hits << std::endl + << "Point pool misses: " << t.m_pointPool.m_misses << std::endl; + #endif + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/RTree.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/RTree.h new file mode 100644 index 000000000..cb4e00452 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/RTree.h @@ -0,0 +1,201 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Statistics.h" +#include "Node.h" +#include "PointerPoolNode.h" + +namespace SpatialIndex +{ + namespace RTree + { + class RTree : public ISpatialIndex + { + //class NNEntry; + + public: + RTree(IStorageManager&, Tools::PropertySet&); + // String Value Description + // ---------------------------------------------- + // IndexIndentifier VT_LONG If specified an existing index will be openened from the supplied + // storage manager with the given index id. Behaviour is unspecified + // if the index id or the storage manager are incorrect. + // Dimension VT_ULONG Dimensionality of the data that will be inserted. + // IndexCapacity VT_ULONG The index node capacity. Default is 100. + // LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. + // FillFactor VT_DOUBLE The fill factor. Default is 70% + // TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar + // NearMinimumOverlapFactor VT_ULONG Default is 32. + // SplitDistributionFactor VT_DOUBLE Default is 0.4 + // ReinsertFactor VT_DOUBLE Default is 0.3 + // EnsureTightMBRs VT_BOOL Default is true + // IndexPoolCapacity VT_LONG Default is 100 + // LeafPoolCapacity VT_LONG Default is 100 + // RegionPoolCapacity VT_LONG Default is 1000 + // PointPoolCapacity VT_LONG Default is 500 + + virtual ~RTree(); + + + + // + // ISpatialIndex interface + // + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type shapeIdentifier); + virtual bool deleteData(const IShape& shape, id_type id); + virtual void containsWhatQuery(const IShape& query, IVisitor& v); + virtual void intersectsWithQuery(const IShape& query, IVisitor& v); + virtual void pointLocationQuery(const Point& query, IVisitor& v); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator&); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v); + virtual void selfJoinQuery(const IShape& s, IVisitor& v); + virtual void queryStrategy(IQueryStrategy& qs); + virtual void getIndexProperties(Tools::PropertySet& out) const; + virtual void addCommand(ICommand* pCommand, CommandType ct); + virtual bool isIndexValid(); + virtual void getStatistics(IStatistics** out) const; + + private: + void initNew(Tools::PropertySet&); + void initOld(Tools::PropertySet& ps); + void storeHeader(); + void loadHeader(); + + void insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id); + void insertData_impl(uint32_t dataLength, byte* pData, Region& mbr, id_type id, uint32_t level, byte* overflowTable); + bool deleteData_impl(const Region& mbr, id_type id); + + id_type writeNode(Node*); + NodePtr readNode(id_type page); + void deleteNode(Node*); + + void rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v); + void selfJoinQuery(id_type id1, id_type id2, const Region& r, IVisitor& vis); + + IStorageManager* m_pStorageManager; + + id_type m_rootID, m_headerID; + + RTreeVariant m_treeVariant; + + double m_fillFactor; + + uint32_t m_indexCapacity; + + uint32_t m_leafCapacity; + + uint32_t m_nearMinimumOverlapFactor; + // The R*-Tree 'p' constant, for calculating nearly minimum overlap cost. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.1] + + double m_splitDistributionFactor; + // The R*-Tree 'm' constant, for calculating spliting distributions. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.2] + + double m_reinsertFactor; + // The R*-Tree 'p' constant, for removing entries at reinserts. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.3] + + uint32_t m_dimension; + + Region m_infiniteRegion; + + Statistics m_stats; + + bool m_bTightMBRs; + + Tools::PointerPool<Point> m_pointPool; + Tools::PointerPool<Region> m_regionPool; + Tools::PointerPool<Node> m_indexPool; + Tools::PointerPool<Node> m_leafPool; + + std::vector<Tools::SmartPointer<ICommand> > m_writeNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_readNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_deleteNodeCommands; + +#ifdef HAVE_PTHREAD_H + pthread_rwlock_t m_rwLock; +#else + bool m_rwLock; +#endif + + + + + class NNEntry + { + public: + id_type m_id; + IEntry* m_pEntry; + double m_minDist; + + NNEntry(id_type id, IEntry* e, double f) : m_id(id), m_pEntry(e), m_minDist(f) {} + ~NNEntry() {} + + struct ascending : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_minDist > __y->m_minDist; } + }; + }; // NNEntry + + class NNComparator : public INearestNeighborComparator + { + public: + double getMinimumDistance(const IShape& query, const IShape& entry) + { + return query.getMinimumDistance(entry); + } + + double getMinimumDistance(const IShape& query, const IData& data) + { + IShape* pS; + data.getShape(&pS); + double ret = query.getMinimumDistance(*pS); + delete pS; + return ret; + } + }; // NNComparator + + class ValidateEntry + { + public: + ValidateEntry(Region& r, NodePtr& pNode) : m_parentMBR(r), m_pNode(pNode) {} + + Region m_parentMBR; + NodePtr m_pNode; + }; // ValidateEntry + + friend class Node; + friend class Leaf; + friend class Index; + friend class BulkLoader; + + friend std::ostream& operator<<(std::ostream& os, const RTree& t); + }; // RTree + + std::ostream& operator<<(std::ostream& os, const RTree& t); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Statistics.cc b/sci-libs/libspatialindex/svn/trunk/src/rtree/Statistics.cc new file mode 100644 index 000000000..d79e5097d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Statistics.cc @@ -0,0 +1,172 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" + +#include "Statistics.h" + +using namespace SpatialIndex::RTree; + +Statistics::Statistics() +{ + reset(); +} + +Statistics::Statistics(const Statistics& s) +{ + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u32TreeHeight = s.m_u32TreeHeight; + m_nodesInLevel = s.m_nodesInLevel; +} + +Statistics::~Statistics() +{ +} + +Statistics& Statistics::operator=(const Statistics& s) +{ + if (this != &s) + { + m_u64Reads = s.m_u64Reads; + m_u64Writes = s.m_u64Writes; + m_u64Splits = s.m_u64Splits; + m_u64Hits = s.m_u64Hits; + m_u64Misses = s.m_u64Misses; + m_u32Nodes = s.m_u32Nodes; + m_u64Adjustments = s.m_u64Adjustments; + m_u64QueryResults = s.m_u64QueryResults; + m_u64Data = s.m_u64Data; + m_u32TreeHeight = s.m_u32TreeHeight; + m_nodesInLevel = s.m_nodesInLevel; + } + + return *this; +} + +uint64_t Statistics::getReads() const +{ + return m_u64Reads; +} + +uint64_t Statistics::getWrites() const +{ + return m_u64Writes; +} + +uint32_t Statistics::getNumberOfNodes() const +{ + return m_u32Nodes; +} + +uint64_t Statistics::getNumberOfData() const +{ + return m_u64Data; +} + +uint64_t Statistics::getSplits() const +{ + return m_u64Splits; +} + +uint64_t Statistics::getHits() const +{ + return m_u64Hits; +} + +uint64_t Statistics::getMisses() const +{ + return m_u64Misses; +} + +uint64_t Statistics::getAdjustments() const +{ + return m_u64Adjustments; +} + +uint64_t Statistics::getQueryResults() const +{ + return m_u64QueryResults; +} + +uint32_t Statistics::getTreeHeight() const +{ + return m_u32TreeHeight; +} + +uint32_t Statistics::getNumberOfNodesInLevel(uint32_t l) const +{ + uint32_t u32Nodes; + try + { + u32Nodes = m_nodesInLevel.at(l); + } + catch (...) + { + throw Tools::IndexOutOfBoundsException(l); + } + + return u32Nodes; +} + +void Statistics::reset() +{ + m_u64Reads = 0; + m_u64Writes = 0; + m_u64Splits = 0; + m_u64Hits = 0; + m_u64Misses = 0; + m_u32Nodes = 0; + m_u64Adjustments = 0; + m_u64QueryResults = 0; + m_u64Data = 0; + m_u32TreeHeight = 0; + m_nodesInLevel.clear(); +} + +std::ostream& SpatialIndex::RTree::operator<<(std::ostream& os, const Statistics& s) +{ + os << "Reads: " << s.m_u64Reads << std::endl + << "Writes: " << s.m_u64Writes << std::endl + << "Hits: " << s.m_u64Hits << std::endl + << "Misses: " << s.m_u64Misses << std::endl + << "Tree height: " << s.m_u32TreeHeight << std::endl + << "Number of data: " << s.m_u64Data << std::endl + << "Number of nodes: " << s.m_u32Nodes << std::endl; + + for (uint32_t u32Level = 0; u32Level < s.m_u32TreeHeight; ++u32Level) + { + os << "Level " << u32Level << " pages: " << s.m_nodesInLevel[u32Level] << std::endl; + } + + os << "Splits: " << s.m_u64Splits << std::endl + << "Adjustments: " << s.m_u64Adjustments << std::endl + << "Query results: " << s.m_u64QueryResults << std::endl; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/rtree/Statistics.h b/sci-libs/libspatialindex/svn/trunk/src/rtree/Statistics.h new file mode 100644 index 000000000..389726d88 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/rtree/Statistics.h @@ -0,0 +1,93 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace RTree + { + class RTree; + class Node; + class Leaf; + class Index; + + class Statistics : public SpatialIndex::IStatistics + { + public: + Statistics(); + Statistics(const Statistics&); + virtual ~Statistics(); + Statistics& operator=(const Statistics&); + + // + // IStatistics interface + // + virtual uint64_t getReads() const; + virtual uint64_t getWrites() const; + virtual uint32_t getNumberOfNodes() const; + virtual uint64_t getNumberOfData() const; + + virtual uint64_t getSplits() const; + virtual uint64_t getHits() const; + virtual uint64_t getMisses() const; + virtual uint64_t getAdjustments() const; + virtual uint64_t getQueryResults() const; + virtual uint32_t getTreeHeight() const; + virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const; + + private: + void reset(); + + uint64_t m_u64Reads; + + uint64_t m_u64Writes; + + uint64_t m_u64Splits; + + uint64_t m_u64Hits; + + uint64_t m_u64Misses; + + uint32_t m_u32Nodes; + + uint64_t m_u64Adjustments; + + uint64_t m_u64QueryResults; + + uint64_t m_u64Data; + + uint32_t m_u32TreeHeight; + + std::vector<uint32_t> m_nodesInLevel; + + friend class RTree; + friend class Node; + friend class Index; + friend class Leaf; + friend class BulkLoader; + + friend std::ostream& operator<<(std::ostream& os, const Statistics& s); + }; // Statistics + + std::ostream& operator<<(std::ostream& os, const Statistics& s); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/all-wcprops new file mode 100644 index 000000000..bacdee811 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/all-wcprops @@ -0,0 +1,65 @@ +K 25 +svn:wc:ra_dav:version-url +V 62 +/spatialindex/!svn/ver/202/spatialindex/trunk/src/spatialindex +END +TimeRegion.cc +K 25 +svn:wc:ra_dav:version-url +V 76 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/spatialindex/TimeRegion.cc +END +MovingRegion.cc +K 25 +svn:wc:ra_dav:version-url +V 78 +/spatialindex/!svn/ver/179/spatialindex/trunk/src/spatialindex/MovingRegion.cc +END +Region.cc +K 25 +svn:wc:ra_dav:version-url +V 72 +/spatialindex/!svn/ver/202/spatialindex/trunk/src/spatialindex/Region.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 73 +/spatialindex/!svn/ver/45/spatialindex/trunk/src/spatialindex/Makefile.am +END +SpatialIndexImpl.cc +K 25 +svn:wc:ra_dav:version-url +V 81 +/spatialindex/!svn/ver/99/spatialindex/trunk/src/spatialindex/SpatialIndexImpl.cc +END +TimePoint.cc +K 25 +svn:wc:ra_dav:version-url +V 75 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/spatialindex/TimePoint.cc +END +MovingPoint.cc +K 25 +svn:wc:ra_dav:version-url +V 77 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/spatialindex/MovingPoint.cc +END +Point.cc +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/spatialindex/Point.cc +END +SpatialIndexImpl.h +K 25 +svn:wc:ra_dav:version-url +V 80 +/spatialindex/!svn/ver/99/spatialindex/trunk/src/spatialindex/SpatialIndexImpl.h +END +LineSegment.cc +K 25 +svn:wc:ra_dav:version-url +V 77 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/spatialindex/LineSegment.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/dir-prop-base new file mode 100644 index 000000000..ea9b95e8a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/dir-prop-base @@ -0,0 +1,9 @@ +K 10 +svn:ignore +V 33 +Makefile.in +.libs +.deps +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/entries new file mode 100644 index 000000000..927718e38 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/entries @@ -0,0 +1,368 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/spatialindex +http://svn.gispython.org/spatialindex + + + +2011-03-01T14:50:59.673579Z +202 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +TimeRegion.cc +file + + + + +2011-08-01T00:42:34.661911Z +62277830274cb167e9ec0398084b2dbc +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +11360 + +MovingRegion.cc +file + + + + +2011-08-01T00:42:34.661911Z +5a2ae3cdefaabc9ae84bd5511ec35219 +2010-03-30T20:18:40.573111Z +179 +hobu + + + + + + + + + + + + + + + + + + + + + +40320 + +Region.cc +file + + + + +2011-08-01T00:42:34.674138Z +b09532912891826f971cbf77c37de29a +2011-03-01T14:50:59.673579Z +202 +mhadji + + + + + + + + + + + + + + + + + + + + + +13432 + +Makefile.am +file + + + + +2011-08-01T00:42:34.674138Z +0399288962ff138cc73334b8e3b8ce9c +2008-01-17T23:34:01.575758Z +45 +hobu + + + + + + + + + + + + + + + + + + + + + +290 + +SpatialIndexImpl.cc +file + + + + +2011-08-01T00:42:34.674138Z +2f757bb99d300514fbaf8fed62aae461 +2009-07-18T22:19:07.374702Z +99 +mhadji + + + + + + + + + + + + + + + + + + + + + +2638 + +TimePoint.cc +file + + + + +2011-08-01T00:42:34.674138Z +caaaa671695b7e2812711c81405eae55 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +7136 + +MovingPoint.cc +file + + + + +2011-08-01T00:42:34.717146Z +d4d894f9e6b1c8643d1136f7c9d96d56 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +8000 + +Point.cc +file + + + + +2011-08-01T00:42:34.717146Z +231b1432a5696b1b7292c803a53eee9c +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +5720 + +SpatialIndexImpl.h +file + + + + +2011-08-01T00:42:34.717146Z +067fba191ef05d4c1f218c1626912fb0 +2009-07-18T22:19:07.374702Z +99 +mhadji + + + + + + + + + + + + + + + + + + + + + +1127 + +LineSegment.cc +file + + + + +2011-08-01T00:42:34.717146Z +7d9e92b721a313b8d30fee5d86467b93 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +11337 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/LineSegment.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/LineSegment.cc.svn-base new file mode 100644 index 000000000..1653f15da --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/LineSegment.cc.svn-base @@ -0,0 +1,388 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +LineSegment::LineSegment() + : m_dimension(0), m_pStartPoint(0), m_pEndPoint(0) +{ +} + +LineSegment::LineSegment(const double* pStartPoint, const double* pEndPoint, uint32_t dimension) + : m_dimension(dimension) +{ + // no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + memcpy(m_pStartPoint, pStartPoint, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, pEndPoint, m_dimension * sizeof(double)); +} + +LineSegment::LineSegment(const Point& startPoint, const Point& endPoint) + : m_dimension(startPoint.m_dimension) +{ + if (startPoint.m_dimension != endPoint.m_dimension) + throw Tools::IllegalArgumentException( + "LineSegment::LineSegment: Points have different dimensionalities." + ); + + // no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + memcpy(m_pStartPoint, startPoint.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, endPoint.m_pCoords, m_dimension * sizeof(double)); +} + +LineSegment::LineSegment(const LineSegment& l) + : m_dimension(l.m_dimension) +{ + // no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + memcpy(m_pStartPoint, l.m_pStartPoint, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, l.m_pEndPoint, m_dimension * sizeof(double)); +} + +LineSegment::~LineSegment() +{ + delete[] m_pStartPoint; + delete[] m_pEndPoint; +} + +LineSegment& LineSegment::operator=(const LineSegment& l) +{ + if (this != &l) + { + makeDimension(l.m_dimension); + memcpy(m_pStartPoint, l.m_pStartPoint, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, l.m_pEndPoint, m_dimension * sizeof(double)); + } + + return *this; +} + +bool LineSegment::operator==(const LineSegment& l) const +{ + if (m_dimension != l.m_dimension) + throw Tools::IllegalArgumentException( + "LineSegment::operator==: LineSegments have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pStartPoint[i] < l.m_pStartPoint[i] - std::numeric_limits<double>::epsilon() || + m_pStartPoint[i] > l.m_pStartPoint[i] + std::numeric_limits<double>::epsilon()) return false; + + if ( + m_pEndPoint[i] < l.m_pEndPoint[i] - std::numeric_limits<double>::epsilon() || + m_pEndPoint[i] > l.m_pEndPoint[i] + std::numeric_limits<double>::epsilon()) return false; + } + + return true; +} + +// +// IObject interface +// +LineSegment* LineSegment::clone() +{ + return new LineSegment(*this); +} + +// +// ISerializable interface +// +uint32_t LineSegment::getByteArraySize() +{ + return (sizeof(uint32_t) + m_dimension * sizeof(double) * 2); +} + +void LineSegment::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + makeDimension(dimension); + memcpy(m_pStartPoint, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pEndPoint, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void LineSegment::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, m_pStartPoint, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pEndPoint, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IShape interface +// +bool LineSegment::intersectsShape(const IShape& s) const +{ + throw Tools::IllegalStateException( + "LineSegment::intersectsShape: Not implemented yet!" + ); +} + +bool LineSegment::containsShape(const IShape& s) const +{ + return false; +} + +bool LineSegment::touchesShape(const IShape& s) const +{ + throw Tools::IllegalStateException( + "LineSegment::touchesShape: Not implemented yet!" + ); +} + +void LineSegment::getCenter(Point& out) const +{ + double* coords = new double[m_dimension]; + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + coords[cDim] = + (std::abs(m_pStartPoint[cDim] - m_pEndPoint[cDim]) / 2.0) + + std::min(m_pStartPoint[cDim], m_pEndPoint[cDim]); + } + + out = Point(coords, m_dimension); + delete[] coords; +} + +uint32_t LineSegment::getDimension() const +{ + return m_dimension; +} + +void LineSegment::getMBR(Region& out) const +{ + double* low = new double[m_dimension]; + double* high = new double[m_dimension]; + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + low[cDim] = std::min(m_pStartPoint[cDim], m_pEndPoint[cDim]); + high[cDim] = std::max(m_pStartPoint[cDim], m_pEndPoint[cDim]); + } + + out = Region(low, high, m_dimension); + delete[] low; + delete[] high; +} + +double LineSegment::getArea() const +{ + return 0.0; +} + +double LineSegment::getMinimumDistance(const IShape& s) const +{ + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) + { + return getMinimumDistance(*ppt); + } + +/* + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->getMinimumDistance(*this); + } +*/ + + throw Tools::IllegalStateException( + "LineSegment::getMinimumDistance: Not implemented yet!" + ); +} + +double LineSegment::getMinimumDistance(const Point& p) const +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getMinimumDistance: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getMinimumDistance: Distance for high dimensional spaces not supported!" + ); + + if (m_pEndPoint[0] >= m_pStartPoint[0] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[0] <= m_pStartPoint[0] + std::numeric_limits<double>::epsilon()) return std::abs(p.m_pCoords[0] - m_pStartPoint[0]); + + if (m_pEndPoint[1] >= m_pStartPoint[1] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[1] <= m_pStartPoint[1] + std::numeric_limits<double>::epsilon()) return std::abs(p.m_pCoords[1] - m_pStartPoint[1]); + + double x1 = m_pStartPoint[0]; + double x2 = m_pEndPoint[0]; + double x0 = p.m_pCoords[0]; + double y1 = m_pStartPoint[1]; + double y2 = m_pEndPoint[1]; + double y0 = p.m_pCoords[1]; + + return std::abs((x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1)) / (std::sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))); +} + +// assuming moving from start to end, positive distance is from right hand side. +double LineSegment::getRelativeMinimumDistance(const Point& p) const +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMinimumDistance: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMinimumDistance: Distance for high dimensional spaces not supported!" + ); + + if (m_pEndPoint[0] >= m_pStartPoint[0] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[0] <= m_pStartPoint[0] + std::numeric_limits<double>::epsilon()) + { + if (m_pStartPoint[1] < m_pEndPoint[1]) return m_pStartPoint[0] - p.m_pCoords[0]; + if (m_pStartPoint[1] >= m_pEndPoint[1]) return p.m_pCoords[0] - m_pStartPoint[0]; + } + + if (m_pEndPoint[1] >= m_pStartPoint[1] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[1] <= m_pStartPoint[1] + std::numeric_limits<double>::epsilon()) + { + if (m_pStartPoint[0] < m_pEndPoint[0]) return p.m_pCoords[1] - m_pStartPoint[1]; + if (m_pStartPoint[0] >= m_pEndPoint[0]) return m_pStartPoint[1] - p.m_pCoords[1]; + } + + double x1 = m_pStartPoint[0]; + double x2 = m_pEndPoint[0]; + double x0 = p.m_pCoords[0]; + double y1 = m_pStartPoint[1]; + double y2 = m_pEndPoint[1]; + double y0 = p.m_pCoords[1]; + + return ((x1 - x0) * (y2 - y1) - (x2 - x1) * (y1 - y0)) / (std::sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))); +} + +double LineSegment::getRelativeMaximumDistance(const Region& r) const +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMaximumDistance: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMaximumDistance: Distance for high dimensional spaces not supported!" + ); + + // clockwise. + double d1 = getRelativeMinimumDistance(Point(r.m_pLow, 2)); + + double coords[2]; + coords[0] = r.m_pLow[0]; + coords[1] = r.m_pHigh[1]; + double d2 = getRelativeMinimumDistance(Point(coords, 2)); + + double d3 = getRelativeMinimumDistance(Point(r.m_pHigh, 2)); + + coords[0] = r.m_pHigh[0]; + coords[1] = r.m_pLow[1]; + double d4 = getRelativeMinimumDistance(Point(coords, 2)); + + return std::max(d1, std::max(d2, std::max(d3, d4))); +} + +double LineSegment::getAngleOfPerpendicularRay() +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getAngleOfPerpendicularRay: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getAngleOfPerpendicularRay: Distance for high dimensional spaces not supported!" + ); + + if (m_pStartPoint[0] >= m_pEndPoint[0] - std::numeric_limits<double>::epsilon() && + m_pStartPoint[0] <= m_pEndPoint[0] + std::numeric_limits<double>::epsilon()) return 0.0; + + if (m_pStartPoint[1] >= m_pEndPoint[1] - std::numeric_limits<double>::epsilon() && + m_pStartPoint[1] <= m_pEndPoint[1] + std::numeric_limits<double>::epsilon()) return M_PI_2; + + return std::atan(-(m_pStartPoint[0] - m_pEndPoint[0]) / (m_pStartPoint[1] - m_pEndPoint[1])); +} + +void LineSegment::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pStartPoint[cIndex] = std::numeric_limits<double>::max(); + m_pEndPoint[cIndex] = std::numeric_limits<double>::max(); + } +} + +void LineSegment::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pStartPoint; + delete[] m_pEndPoint; + + // remember that this is not a constructor. The object will be destructed normally if + // something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state. + m_pStartPoint = 0; + m_pEndPoint = 0; + + m_dimension = dimension; + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + } +} + +std::ostream& operator<<(std::ostream& os, const LineSegment& l) +{ + for (uint32_t cDim = 0; cDim < l.m_dimension; ++cDim) + { + os << l.m_pStartPoint[cDim] << ", " << l.m_pEndPoint[cDim] << " "; + } + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..6a0adc928 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = liblibrary.la +INCLUDES = -I../../include +liblibrary_la_SOURCES = Point.cc Region.cc LineSegment.cc MovingPoint.cc MovingRegion.cc TimePoint.cc TimeRegion.cc SpatialIndexImpl.cc SpatialIndexImpl.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/MovingPoint.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/MovingPoint.cc.svn-base new file mode 100644 index 000000000..d3a33cb59 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/MovingPoint.cc.svn-base @@ -0,0 +1,299 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +MovingPoint::MovingPoint() +{ +} + +MovingPoint::MovingPoint(const double* pCoords, const double* pVCoords, const IInterval& ti, uint32_t dimension) +{ + initialize(pCoords, pVCoords, ti.getLowerBound(), ti.getUpperBound(), dimension); +} + +MovingPoint::MovingPoint(const double* pCoords, const double* pVCoords, double tStart, double tEnd, uint32_t dimension) +{ + initialize(pCoords, pVCoords, tStart, tEnd, dimension); +} + +MovingPoint::MovingPoint(const Point& p, const Point& vp, const IInterval& ti) +{ + if (p.m_dimension != vp.m_dimension) throw Tools::IllegalArgumentException("MovingPoint: Points have different number of dimensions."); + + initialize(p.m_pCoords, vp.m_pCoords, ti.getLowerBound(), ti.getUpperBound(), p.m_dimension); +} + +MovingPoint::MovingPoint(const Point& p, const Point& vp, double tStart, double tEnd) +{ + if (p.m_dimension != vp.m_dimension) throw Tools::IllegalArgumentException("MovingPoint: Points have different number of dimensions."); + + initialize(p.m_pCoords, vp.m_pCoords, tStart, tEnd, p.m_dimension); +} + +MovingPoint::MovingPoint(const MovingPoint& p) +{ + m_startTime = p.m_startTime; + m_endTime = p.m_endTime; + m_pCoords = 0; + + m_dimension = p.m_dimension; + + try + { + m_pCoords = new double[m_dimension]; + m_pVCoords = new double[m_dimension]; + } + catch (...) + { + delete[] m_pCoords; + throw; + } + + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pVCoords, p.m_pVCoords, m_dimension * sizeof(double)); +} + +MovingPoint::~MovingPoint() +{ + delete[] m_pVCoords; +} + +void MovingPoint::initialize( + const double* pCoords, const double* pVCoords, + double tStart, double tEnd, uint32_t dimension) +{ + m_dimension = dimension; + m_startTime = tStart; + m_endTime = tEnd; + m_pCoords = 0; + + if (m_endTime <= m_startTime) throw Tools::IllegalArgumentException("MovingPoint: Cannot support degenerate time intervals."); + + try + { + m_pCoords = new double[m_dimension]; + m_pVCoords = new double[m_dimension]; + } + catch (...) + { + delete[] m_pCoords; + throw; + } + + // first store the point coordinates, than the point velocities. + memcpy(m_pCoords, pCoords, m_dimension * sizeof(double)); + memcpy(m_pVCoords, pVCoords, m_dimension * sizeof(double)); +} + +MovingPoint& MovingPoint::operator=(const MovingPoint& p) +{ + if (this != &p) + { + makeDimension(p.m_dimension); + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pVCoords, p.m_pVCoords, m_dimension * sizeof(double)); + + m_startTime = p.m_startTime; + m_endTime = p.m_endTime; + } + + return *this; +} + +bool MovingPoint::operator==(const MovingPoint& p) const +{ + if ( + m_startTime < p.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > p.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < p.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > p.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t cDim = 0; cDim < 2 * m_dimension; ++cDim) + { + if ( + m_pCoords[cDim] < p.m_pCoords[cDim] - std::numeric_limits<double>::epsilon() || + m_pCoords[cDim] > p.m_pCoords[cDim] + std::numeric_limits<double>::epsilon() || + m_pVCoords[cDim] < p.m_pVCoords[cDim] - std::numeric_limits<double>::epsilon() || + m_pVCoords[cDim] > p.m_pVCoords[cDim] + std::numeric_limits<double>::epsilon()) + return false; + } + + return true; +} + +double MovingPoint::getCoord(uint32_t d, double t) const +{ + if (d < 0 && d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + if (t >= m_endTime) return m_pCoords[d] + m_pVCoords[d] * (m_endTime - m_startTime); + else if (t <= m_startTime) return m_pCoords[d] + m_pVCoords[d] * m_startTime; + else return m_pCoords[d] + m_pVCoords[d] * (t - m_startTime); +} + +double MovingPoint::getProjectedCoord(uint32_t d, double t) const +{ + if (d < 0 && d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pCoords[d] + m_pVCoords[d] * (t - m_startTime); +} + +double MovingPoint::getVCoord(uint32_t d) const +{ + if (d < 0 && d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pVCoords[d]; +} + +void MovingPoint::getPointAtTime(double t, Point& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + out.m_pCoords[cDim] = getCoord(cDim, t); + } +} + +// +// IObject interface +// +MovingPoint* MovingPoint::clone() +{ + return new MovingPoint(*this); +} + +// +// ISerializable interface +// +uint32_t MovingPoint::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + 2 * m_dimension * sizeof(double)); +} + +void MovingPoint::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pCoords, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pVCoords, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void MovingPoint::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, m_pCoords, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pVCoords, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IEvolvingShape interface +// +void MovingPoint::getVMBR(Region& out) const +{ + out.makeDimension(m_dimension); + memcpy(out.m_pLow, m_pVCoords, m_dimension * sizeof(double)); + memcpy(out.m_pHigh, m_pVCoords, m_dimension * sizeof(double)); +} + +void MovingPoint::getMBRAtTime(double t, Region& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + out.m_pLow[cDim] = getCoord(cDim, t); + out.m_pHigh[cDim] = getCoord(cDim, t); + } +} + +void MovingPoint::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pCoords[cIndex] = std::numeric_limits<double>::max(); + m_pVCoords[cIndex] = -std::numeric_limits<double>::max(); + } + + m_startTime = std::numeric_limits<double>::max(); + m_endTime = -std::numeric_limits<double>::max(); +} + +void MovingPoint::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pCoords; + delete[] m_pVCoords; + m_pCoords = 0; m_pVCoords = 0; + + m_dimension = dimension; + m_pCoords = new double[m_dimension]; + m_pVCoords = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const MovingPoint& pt) +{ + uint32_t i; + + os << "Coords: "; + for (i = 0; i < pt.m_dimension; ++i) + { + os << pt.m_pCoords[i] << " "; + } + + os << "VCoords: "; + for (i = 0; i < pt.m_dimension; ++i) + { + os << pt.m_pVCoords[i] << " "; + } + + os << ", Start: " << pt.m_startTime << ", End: " << pt.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/MovingRegion.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/MovingRegion.cc.svn-base new file mode 100644 index 000000000..8f54e4a37 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/MovingRegion.cc.svn-base @@ -0,0 +1,1231 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +/* + * Does not support degenerate time intervals or shrinking regions. +*/ + + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +MovingRegion::MovingRegion() + : TimeRegion(), m_pVLow(0), m_pVHigh(0) +{ +} + +MovingRegion::MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + const IInterval& ivT, uint32_t dimension) +{ + initialize(pLow, pHigh, pVLow, pVHigh, ivT.getLowerBound(), ivT.getUpperBound(), dimension); +} + +MovingRegion::MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension) +{ + initialize(pLow, pHigh, pVLow, pVHigh, tStart, tEnd, dimension); +} + +MovingRegion::MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + const IInterval& ivT) +{ + if (low.m_dimension != high.m_dimension || low.m_dimension != vlow.m_dimension || vlow.m_dimension != vhigh.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize( + low.m_pCoords, high.m_pCoords, vlow.m_pCoords, vhigh.m_pCoords, + ivT.getLowerBound(), ivT.getUpperBound(), low.m_dimension); +} + +MovingRegion::MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + double tStart, double tEnd) +{ + if (low.m_dimension != high.m_dimension || low.m_dimension != vlow.m_dimension || vlow.m_dimension != vhigh.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize( + low.m_pCoords, high.m_pCoords, vlow.m_pCoords, vhigh.m_pCoords, + tStart, tEnd, low.m_dimension); +} + +MovingRegion::MovingRegion( + const Region& mbr, const Region& vbr, const IInterval& ivT) +{ + if (mbr.m_dimension != vbr.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize(mbr.m_pLow, mbr.m_pHigh, vbr.m_pLow, vbr.m_pHigh, ivT.getLowerBound(), ivT.getUpperBound(), mbr.m_dimension); +} + +MovingRegion::MovingRegion( + const Region& mbr, const Region& vbr, double tStart, double tEnd) +{ + if (mbr.m_dimension != vbr.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize(mbr.m_pLow, mbr.m_pHigh, vbr.m_pLow, vbr.m_pHigh, tStart, tEnd, mbr.m_dimension); +} + +MovingRegion::MovingRegion(const MovingPoint& low, const MovingPoint& high) +{ + m_startTime = low.m_startTime; + m_endTime = high.m_endTime;; + m_dimension = low.m_dimension; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + if (m_endTime <= m_startTime) throw Tools::IllegalArgumentException("MovingRegion: Cannot support degenerate time intervals."); + + if (low.m_dimension != high.m_dimension) throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + + } + catch (...) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + throw; + } + + memcpy(m_pLow, low.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pHigh, high.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pVLow, low.m_pVCoords, m_dimension * sizeof(double)); + memcpy(m_pVHigh, high.m_pVCoords, m_dimension * sizeof(double)); +} + +MovingRegion::MovingRegion(const MovingRegion& r) +{ + m_startTime = r.m_startTime; + m_endTime = r.m_endTime; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + m_dimension = r.m_dimension; + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + throw; + } + + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + memcpy(m_pVLow, r.m_pVLow, m_dimension * sizeof(double)); + memcpy(m_pVHigh, r.m_pVHigh, m_dimension * sizeof(double)); +} + +void MovingRegion::initialize( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension) +{ + m_startTime = tStart; + m_endTime = tEnd; + m_dimension = dimension; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + if (m_endTime <= m_startTime) throw Tools::IllegalArgumentException("MovingRegion: Cannot support degenerate time intervals."); + +#ifndef NDEBUG + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (pLow[cDim] > pHigh[cDim]) throw Tools::IllegalArgumentException("MovingRegion: Low point has larger coordinates than High point."); + } +#endif + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + throw; + } + + // first store the point coordinates, than the point velocities. + memcpy(m_pLow, pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, pHigh, m_dimension * sizeof(double)); + memcpy(m_pVLow, pVLow, m_dimension * sizeof(double)); + memcpy(m_pVHigh, pVHigh, m_dimension * sizeof(double)); +} + +MovingRegion::~MovingRegion() +{ + delete[] m_pVLow; + delete[] m_pVHigh; +} + +MovingRegion& MovingRegion::operator=(const MovingRegion& r) +{ + if(this != &r) + { + makeDimension(r.m_dimension); + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + memcpy(m_pVLow, r.m_pVLow, m_dimension * sizeof(double)); + memcpy(m_pVHigh, r.m_pVHigh, m_dimension * sizeof(double)); + + m_startTime = r.m_startTime; + m_endTime = r.m_endTime; + + assert(m_startTime < m_endTime); + } + + return *this; +} + +bool MovingRegion::operator==(const MovingRegion& r) const +{ + if (m_startTime < r.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > r.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < r.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > r.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pLow[i] < r.m_pLow[i] - std::numeric_limits<double>::epsilon() || + m_pLow[i] > r.m_pLow[i] + std::numeric_limits<double>::epsilon() || + m_pHigh[i] < r.m_pHigh[i] - std::numeric_limits<double>::epsilon() || + m_pHigh[i] > r.m_pHigh[i] + std::numeric_limits<double>::epsilon() || + m_pVLow[i] < r.m_pVLow[i] - std::numeric_limits<double>::epsilon() || + m_pVLow[i] > r.m_pVLow[i] + std::numeric_limits<double>::epsilon() || + m_pVHigh[i] < r.m_pVHigh[i] - std::numeric_limits<double>::epsilon() || + m_pVHigh[i] > r.m_pVHigh[i] + std::numeric_limits<double>::epsilon()) + return false; + } + return true; +} + +bool MovingRegion::isShrinking() const +{ + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (m_pVHigh[cDim] < m_pVLow[cDim]) return true; + } + return false; +} + +// assumes that the region is not moving before and after start and end time. +double MovingRegion::getLow(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + if (t > m_endTime) return m_pLow[d] + m_pVLow[d] * (m_endTime - m_startTime); + else if (t < m_startTime) return m_pLow[d]; + else return m_pLow[d] + m_pVLow[d] * (t - m_startTime); +} + +// assumes that the region is not moving before and after start and end time. +double MovingRegion::getHigh(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + if (t > m_endTime) return m_pHigh[d] + m_pVHigh[d] * (m_endTime - m_startTime); + else if (t < m_startTime) return m_pHigh[d]; + else return m_pHigh[d] + m_pVHigh[d] * (t - m_startTime); +} + +// assuming that the region kept moving. +double MovingRegion::getExtrapolatedLow(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pLow[d] + m_pVLow[d] * (t - m_startTime); +} + +// assuming that the region kept moving. +double MovingRegion::getExtrapolatedHigh(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pHigh[d] + m_pVHigh[d] * (t - m_startTime); +} + +double MovingRegion::getVLow(uint32_t d) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pVLow[d]; +} + +double MovingRegion::getVHigh(uint32_t d) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pVHigh[d]; +} + +bool MovingRegion::intersectsRegionInTime(const MovingRegion& r) const +{ + Tools::Interval ivOut; + return intersectsRegionInTime(r, ivOut); +} + +bool MovingRegion::intersectsRegionInTime(const MovingRegion& r, IInterval& ivOut) const +{ + return intersectsRegionInTime(r, r, ivOut); +} + +// if tmin, tmax are infinity then this will not work correctly (everything will always intersect). +// does not work for shrinking regions. +// does not work with degenerate time-intervals. +// +// WARNING: this will return true even if one region completely contains the other, since +// their areas do intersect in that case! +// +// there are various cases here: +// 1. one region contains the other. +// 2. one boundary of one region is always contained indide the other region, while the other +// boundary is not (so no boundaries will ever intersect). +// 3. either the upper or lower boundary of one region intersects a boundary of the other. +bool MovingRegion::intersectsRegionInTime(const IInterval& ivPeriod, const MovingRegion& r, IInterval& ivOut) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("intersectsRegionInTime: MovingRegions have different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(r.m_startTime < r.m_endTime); + assert(ivPeriod.getLowerBound() < ivPeriod.getUpperBound()); + assert(isShrinking() == false && r.isShrinking() == false); + + // this is needed, since we are assuming below that the two regions have some point of intersection + // inside itPeriod. + if (containsRegionInTime(ivPeriod, r) || r.containsRegionInTime(ivPeriod, *this)) + { + ivOut = ivPeriod; + return true; + } + + double tmin = std::max(m_startTime, r.m_startTime); + double tmax = std::min(m_endTime, r.m_endTime); + + // the regions do not intersect in time. + if (tmax <= tmin) return false; + + tmin = std::max(tmin, ivPeriod.getLowerBound()); + tmax = std::min(tmax, ivPeriod.getUpperBound()); + + // the regions intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return false; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + // I use projected low and high because they are faster and it does not matter. + // The are also necessary for calculating the intersection point with reference time instant 0.0. + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= r.m_startTime && tmax <= r.m_endTime); + + // completely above or bellow in i-th dimension + if ( + (r.getExtrapolatedLow(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) && + r.getExtrapolatedLow(cDim, tmax) >= getExtrapolatedHigh(cDim, tmax)) || + (r.getExtrapolatedHigh(cDim, tmin) < getExtrapolatedLow(cDim, tmin) && + r.getExtrapolatedHigh(cDim, tmax) <= getExtrapolatedLow(cDim, tmax))) + return false; + + // otherwise they intersect inside this interval for sure. Care needs to be taken since + // intersection does not necessarily mean that two line segments intersect. It could be + // that one line segment is completely above/below another, in which case there is no intersection + // point inside tmin, tmax, even though the two region areas do intersect. + + if (r.getExtrapolatedLow(cDim, tmin) > getExtrapolatedHigh(cDim, tmin)) // r above *this at tmin + { + tmin = (getExtrapolatedHigh(cDim, 0.0) - r.getExtrapolatedLow(cDim, 0.0)) / (r.getVLow(cDim) - getVHigh(cDim)); + } + else if (r.getExtrapolatedHigh(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) // r below *this at tmin + { + tmin = (getExtrapolatedLow(cDim, 0.0) - r.getExtrapolatedHigh(cDim, 0.0)) / (r.getVHigh(cDim) - getVLow(cDim)); + } + // else they do not intersect and the boundary might be completely contained in this region. + + if (r.getExtrapolatedLow(cDim, tmax) > getExtrapolatedHigh(cDim, tmax)) // r above *this at tmax + { + tmax = (getExtrapolatedHigh(cDim, 0.0) - r.getExtrapolatedLow(cDim, 0.0)) / (r.getVLow(cDim) - getVHigh(cDim)); + } + else if (r.getExtrapolatedHigh(cDim, tmax) < getExtrapolatedLow(cDim, tmax)) // r below *this at tmax + { + tmax = (getExtrapolatedLow(cDim, 0.0) - r.getExtrapolatedHigh(cDim, 0.0)) / (r.getVHigh(cDim) - getVLow(cDim)); + } + // else they do not intersect and the boundary might be completely contained in this region. + + assert(tmin <= tmax); + } + + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= r.m_startTime && tmax <= r.m_endTime); + + ivOut.setBounds(tmin, tmax); + + return true; +} + +bool MovingRegion::containsRegionInTime(const MovingRegion& r) const +{ + return containsRegionInTime(r, r); +} + +// does not work for shrinking regions. +// works fine for infinite bounds (both tmin and tmax). +// does not work with degenerate time-intervals. +// +// finds if during the intersecting time-interval of r and ivPeriod, r is completely contained in *this. +bool MovingRegion::containsRegionInTime(const IInterval& ivPeriod, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("containsRegionInTime: MovingRegions have different number of dimensions."); + + assert(isShrinking() == false && r.isShrinking() == false); + + double tmin = std::max(ivPeriod.getLowerBound(), r.m_startTime); + double tmax = std::min(ivPeriod.getUpperBound(), r.m_endTime); + + // it should be contained in time. + // it does not make sense if this region is not defined for any part ot [tmin, tmax]. + if (tmax <= tmin || tmin < m_startTime || tmax > m_endTime) return false; + + double intersectionTime; + + // no need to take projected coordinates here, since tmin and tmax are always contained in + // the regions intersecting time-intervals. + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= r.m_startTime && tmax <= r.m_endTime); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + // it should be contained at start time. + if (r.getExtrapolatedHigh(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) || + r.getExtrapolatedLow(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) return false; + + // this will take care of infinite bounds. + if (r.m_pVHigh[cDim] != m_pVHigh[cDim]) + { + intersectionTime = (getExtrapolatedHigh(cDim, 0.0) - r.getExtrapolatedHigh(cDim, 0.0)) / (r.m_pVHigh[cDim] - m_pVHigh[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && r.m_pVHigh[cDim] > m_pVHigh[cDim]) return false; + } + + if (r.m_pVLow[cDim] != m_pVLow[cDim]) + { + intersectionTime = (getExtrapolatedLow(cDim, 0.0) - r.getExtrapolatedLow(cDim, 0.0)) / (r.m_pVLow[cDim] - m_pVLow[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && r.m_pVLow[cDim] < m_pVLow[cDim]) return false; + } + } + + return true; +} + +bool MovingRegion::containsRegionAfterTime(double t, const MovingRegion& r) const +{ + Tools::Interval ivT(t, r.m_endTime); + return containsRegionInTime(ivT, r); +} + +// Returns the area swept by the rectangle in time, in d-dimensional space (without +// including the temporal dimension, that is). +// This is what Saltenis calls Margin (which is different than what Beckmann proposes, +// where he computes only the wireframe -- instead of the surface/volume/etc. -- of the MBR in any dimension). +double MovingRegion::getProjectedSurfaceAreaInTime() const +{ + return getProjectedSurfaceAreaInTime(*this); +} + +double MovingRegion::getProjectedSurfaceAreaInTime(const IInterval& ivI) const +{ + double tmin = std::max(ivI.getLowerBound(), m_startTime); + double tmax = std::min(ivI.getUpperBound(), m_endTime); + + assert(tmin > -std::numeric_limits<double>::max()); + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin <= tmax); + + if (tmin >= tmax - std::numeric_limits<double>::epsilon() && + tmin <= tmax + std::numeric_limits<double>::epsilon()) + return 0.0; + + double dx1, dx2, dx3; + double dv1, dv2, dv3; + double H = tmax - tmin; + + if (m_dimension == 3) + { + dx3 = getExtrapolatedHigh(2, tmin) - getExtrapolatedLow(2, tmin); + dv3 = getVHigh(2) - getVLow(2); + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return + H * (dx1 + dx2 + dx3 + dx1*dx2 + dx1*dx3 + dx2*dx3) + + H*H * (dv1 + dv2 + dv3 + dx1*dv2 + dv1*dx2 + dx1*dv3 + + dv1*dx3 + dx2*dv3 + dv2*dx3) / 2.0 + + H*H*H * (dv1*dv2 + dv1*dv3 + dv2*dv3) / 3.0; + } + else if (m_dimension == 2) + { + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return H * (dx1 + dx2) + H * H * (dv1 + dv2) / 2.0; + } + else if (m_dimension == 1) + { + // marioh: why not use the increase of the length of the interval here? + return 0.0; + } + else + { + throw Tools::IllegalStateException("getProjectedSurfaceAreaInTime: unsupported dimensionality."); + } +} + +double MovingRegion::getCenterDistanceInTime(const MovingRegion& r) const +{ + + return getCenterDistanceInTime(r, r); +} + +double MovingRegion::getCenterDistanceInTime(const IInterval& ivI, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("getCenterDistanceInTime: MovingRegions have different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(r.m_startTime < r.m_endTime); + assert(ivI.getLowerBound() < ivI.getUpperBound()); + + double tmin = std::max(m_startTime, r.m_startTime); + double tmax = std::min(m_endTime, r.m_endTime); + + // the regions do not intersect in time. + if (tmax <= tmin) return 0.0; + + tmin = std::max(tmin, ivI.getLowerBound()); + tmax = std::min(tmax, ivI.getUpperBound()); + + // the regions intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return 0.0; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + if (tmin >= tmax - std::numeric_limits<double>::epsilon() && + tmin <= tmax + std::numeric_limits<double>::epsilon()) + return 0.0; + + double H = tmax - tmin; + + double* dx = new double[m_dimension]; + double* dv = new double[m_dimension]; + double a = 0.0, b = 0.0, c = 0.0, f = 0.0, l = 0.0, m = 0.0, n = 0.0; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + dx[cDim] = + (r.getExtrapolatedLow(cDim, tmin) + r.getExtrapolatedHigh(cDim, tmin)) / 2.0 - + (getExtrapolatedLow(cDim, tmin) + getExtrapolatedHigh(cDim, tmin)) / 2.0; + dv[cDim] = + (r.getVLow(cDim) + r.getVHigh(cDim)) / 2.0 - + (getVLow(cDim) + getVHigh(cDim)) / 2.0; + } + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + a += dv[cDim] * dv[cDim]; + b += 2.0 * dx[cDim] * dv[cDim]; + c += dx[cDim] * dx[cDim]; + } + + if (a == 0.0 && c == 0.0) return 0.0; + if (a == 0.0) return H * std::sqrt(c); + if (c == 0.0) return H * H * std::sqrt(a) / 2.0; + + f = std::sqrt(a * H * H + b * H + c); + l = 2.0 * a * H + b; + m = 4.0 * a * c - b * b; + n = 2.0 * std::sqrt(a); + + delete[] dx; + delete[] dv; + + return (l * f + log(l / n + f) * m / n - b * std::sqrt(c) - std::log(b / n + std::sqrt(c)) * m / n) / (4.0 * a); +} + +// does not work with degenerate time-intervals. +bool MovingRegion::intersectsRegionAtTime(double t, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("intersectsRegionAtTime: MovingRegions have different number of dimensions."); + + // do they contain the time instant? + if (! (m_startTime <= t && t < m_endTime && r.m_startTime <= t && t < r.m_endTime)) return false; + + // do they intersect at that time instant? + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (getExtrapolatedLow(i, t) > r.getExtrapolatedHigh(i, t) || getExtrapolatedHigh(i, t) < r.getExtrapolatedLow(i, t)) return false; + } + return true; +} + +// does not work with degenerate time-intervals. +bool MovingRegion::containsRegionAtTime(double t, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("containsRegionAtTime: MovingRegions have different number of dimensions."); + + // do they contain the time instant? + if (! (m_startTime <= t && t < m_endTime && r.m_startTime <= t && t < r.m_endTime)) return false; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (getExtrapolatedLow(cDim, t) > r.getExtrapolatedLow(cDim, t) || getExtrapolatedHigh(cDim, t) < getExtrapolatedHigh(cDim, t)) return false; + } + return true; +} + +bool MovingRegion::intersectsPointInTime(const MovingPoint& p) const +{ + Tools::Interval ivOut; + return intersectsPointInTime(p, ivOut); +} + +bool MovingRegion::intersectsPointInTime(const MovingPoint& p, IInterval& ivOut) const +{ + return intersectsPointInTime(p, p, ivOut); +} + +// if tmin, tmax are infinity then this will not work correctly (everything will always intersect). +// does not work for shrinking regions. +// does not work with degenerate time-intervals. +// FIXME: don't know what happens if tmin is negative infinity. +// +// WARNING: This will return true even if the region completely contains the point, since +// in that case the point trajectory intersects the region area! +bool MovingRegion::intersectsPointInTime(const IInterval& ivPeriod, const MovingPoint& p, IInterval& ivOut) const +{ + if (m_dimension != p.m_dimension) throw Tools::IllegalArgumentException("intersectsPointInTime: MovingPoint has different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(p.m_startTime < p.m_endTime); + assert(ivPeriod.getLowerBound() < ivPeriod.getUpperBound()); + assert(isShrinking() == false); + + if (containsPointInTime(ivPeriod, p)) + { + ivOut = ivPeriod; + return true; + } + + double tmin = std::max(m_startTime, p.m_startTime); + double tmax = std::min(m_endTime, p.m_endTime); + + // the shapes do not intersect in time. + if (tmax <= tmin) return false; + + tmin = std::max(tmin, ivPeriod.getLowerBound()); + tmax = std::min(tmax, ivPeriod.getUpperBound()); + + // the shapes intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return false; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= p.m_startTime && tmax <= p.m_endTime); + + // completely above or bellow in i-th dimension + if ((p.getProjectedCoord(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) && + p.getProjectedCoord(cDim, tmax) >= getExtrapolatedHigh(cDim, tmax)) || + (p.getProjectedCoord(cDim, tmin) < getExtrapolatedLow(cDim, tmin) && + p.getProjectedCoord(cDim, tmax) <= getExtrapolatedLow(cDim, tmax))) + return false; + + // otherwise they intersect inside this interval for sure, since we know that the point is not contained, + // so there is no need to check for 0 divisors, negative values, etc... + + // adjust tmin + if (p.getProjectedCoord(cDim, tmin) > getExtrapolatedHigh(cDim, tmin)) // p above *this at tmin + { + tmin = (getExtrapolatedHigh(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVHigh(cDim)); + } + else if (p.getProjectedCoord(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) // p below *this at tmin + { + tmin = (getExtrapolatedLow(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVLow(cDim)); + } + + // adjust tmax + if (p.getProjectedCoord(cDim, tmax) > getExtrapolatedHigh(cDim, tmax)) // p above *this at tmax + { + tmax = (getExtrapolatedHigh(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVHigh(cDim)); + } + else if (p.getProjectedCoord(cDim, tmax) < getExtrapolatedLow(cDim, tmax)) // p below *this at tmax + { + tmax = (getExtrapolatedLow(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVLow(cDim)); + } + + if (tmin > tmax) return false; + } + + ivOut.setBounds(tmin, tmax); + + return true; +} + +bool MovingRegion::containsPointInTime(const MovingPoint& p) const +{ + return containsPointInTime(p, p); +} + +// does not work for shrinking regions. +// works fine for infinite bounds (both tmin and tmax). +// does not work with degenerate time-intervals. +// +// finds if during the intersecting time-interval of p and ivPeriod, p is completely contained in *this. +bool MovingRegion::containsPointInTime(const IInterval& ivPeriod, const MovingPoint& p) const +{ + if (m_dimension != p.m_dimension) throw Tools::IllegalArgumentException("containsPointInTime: MovingPoint has different number of dimensions."); + + assert(isShrinking() == false); + + double tmin = std::max(ivPeriod.getLowerBound(), p.m_startTime); + double tmax = std::min(ivPeriod.getUpperBound(), p.m_endTime); + + // it should be contained in time. + if (tmax <= tmin || tmin < m_startTime || tmax > m_endTime) return false; + + double intersectionTime; + + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= p.m_startTime && tmax <= p.m_endTime); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + // it should be contained at start time. + if (p.getProjectedCoord(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) || + p.getProjectedCoord(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) return false; + + if (p.m_pVCoords[cDim] != m_pVHigh[cDim]) + { + intersectionTime = (getExtrapolatedHigh(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.m_pVCoords[cDim] - m_pVHigh[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && p.m_pVCoords[cDim] > m_pVHigh[cDim]) return false; + } + + if (p.m_pVCoords[cDim] != m_pVLow[cDim]) + { + intersectionTime = (getExtrapolatedLow(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.m_pVCoords[cDim] - m_pVLow[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && p.m_pVCoords[cDim] < m_pVLow[cDim]) return false; + } + } + + return true; +} + +void MovingRegion::combineRegionInTime(const MovingRegion& r) +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("combineRegionInTime: MovingRegions have different number of dimensions."); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(getExtrapolatedLow(cDim, m_startTime), r.getExtrapolatedLow(cDim, m_startTime)); + m_pHigh[cDim] = std::max(getExtrapolatedHigh(cDim, m_startTime), r.getExtrapolatedHigh(cDim, m_startTime)); + m_pVLow[cDim] = std::min(m_pVLow[cDim], r.m_pVLow[cDim]); + m_pVHigh[cDim] = std::max(m_pVHigh[cDim], r.m_pVHigh[cDim]); + } + + // m_startTime should be modified at the end, since it affects the + // calculation of extrapolated coordinates. + m_startTime = std::min(m_startTime, r.m_startTime); + m_endTime = std::max(m_endTime, r.m_endTime); +} + +void MovingRegion::getCombinedRegionInTime(MovingRegion& out, const MovingRegion& in) const +{ + if (m_dimension != in.m_dimension) throw Tools::IllegalArgumentException("getCombinedProjectedRegionInTime: MovingRegions have different number of dimensions."); + + out = *this; + out.combineRegionInTime(in); +} + +void MovingRegion::combineRegionAfterTime(double t, const MovingRegion& r) +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("combineRegionInTime: MovingRegions have different number of dimensions."); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(getExtrapolatedLow(cDim, t), r.getExtrapolatedLow(cDim, t)); + m_pHigh[cDim] = std::max(getExtrapolatedHigh(cDim, t), r.getExtrapolatedHigh(cDim, t)); + m_pVLow[cDim] = std::min(m_pVLow[cDim], r.m_pVLow[cDim]); + m_pVHigh[cDim] = std::max(m_pVHigh[cDim], r.m_pVHigh[cDim]); + } + + // m_startTime should be modified at the end, since it affects the + // calculation of extrapolated coordinates. + m_startTime = t; + m_endTime = std::max(m_endTime, r.m_endTime); + if (t >= m_endTime) m_endTime = std::numeric_limits<double>::max(); +} + +void MovingRegion::getCombinedRegionAfterTime(double t, MovingRegion& out, const MovingRegion& in) const +{ + if (m_dimension != in.m_dimension) throw Tools::IllegalArgumentException("getCombinedProjectedRegionInTime: MovingRegions have different number of dimensions."); + + out = *this; + out.combineRegionAfterTime(t, in); +} + +double MovingRegion::getIntersectingAreaInTime(const MovingRegion& r) const +{ + return getIntersectingAreaInTime(r, r); +} + +double MovingRegion::getIntersectingAreaInTime(const IInterval& ivI, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("getIntersectingAreaInTime: MovingRegions have different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(r.m_startTime < r.m_endTime); + assert(ivI.getLowerBound() < ivI.getUpperBound()); + assert(isShrinking() == false && r.isShrinking() == false); + + double tmin = std::max(m_startTime, r.m_startTime); + double tmax = std::min(m_endTime, r.m_endTime); + + // the regions do not intersect in time. + if (tmax <= tmin) return 0.0; + + tmin = std::max(tmin, ivI.getLowerBound()); + tmax = std::min(tmax, ivI.getUpperBound()); + + // the regions intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return 0.0; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + Tools::Interval ivIn(tmin, tmax); + Tools::Interval ivOut(ivIn); + + if (! intersectsRegionInTime(ivIn, r, ivOut)) return 0.0; + + ivIn = ivOut; + tmin = ivIn.getLowerBound(); + tmax = ivIn.getUpperBound(); + assert(tmin <= tmax); + + assert(tmin >= ivI.getLowerBound() && tmax <= ivI.getUpperBound()); + + if (containsRegionInTime(ivIn, r)) + { + return r.getAreaInTime(ivIn); + } + else if (r.containsRegionInTime(ivIn, *this)) + { + return getAreaInTime(ivIn); + } + + MovingRegion x = *this; + CrossPoint c; + std::priority_queue<CrossPoint, std::vector<CrossPoint>, CrossPoint::ascending> pq; + + // find points of intersection in all dimensions. + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (getLow(i, tmin) > r.getLow(i, tmin)) + { + x.m_pLow[i] = m_pLow[i]; + x.m_pVLow[i] = m_pVLow[i]; + + if (getLow(i, tmax) < r.getLow(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 0; + c.m_t = (getExtrapolatedLow(i, 0.0) - r.getExtrapolatedLow(i, 0.0)) / (r.getVLow(i) - getVLow(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = &r; + pq.push(c); + } + } + else + { + x.m_pLow[i] = r.m_pLow[i]; + x.m_pVLow[i] = r.m_pVLow[i]; + + if (r.getLow(i, tmax) < getLow(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 0; + c.m_t = (getExtrapolatedLow(i, 0.0) - r.getExtrapolatedLow(i, 0.0)) / (r.getVLow(i) - getVLow(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = this; + pq.push(c); + } + } + + if (getHigh(i, tmin) < r.getHigh(i, tmin)) + { + x.m_pHigh[i] = m_pHigh[i]; + x.m_pVHigh[i] = m_pVHigh[i]; + + if (getHigh(i, tmax) > r.getHigh(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 1; + c.m_t = (getExtrapolatedHigh(i, 0.0) - r.getExtrapolatedHigh(i, 0.0)) / (r.getVHigh(i) - getVHigh(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = &r; + pq.push(c); + } + } + else + { + x.m_pHigh[i] = r.m_pHigh[i]; + x.m_pVHigh[i] = r.m_pVHigh[i]; + + if (r.getHigh(i, tmax) > getHigh(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 1; + c.m_t = (getExtrapolatedHigh(i, 0.0) - r.getExtrapolatedHigh(i, 0.0)) / (r.getVHigh(i) - getVHigh(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = this; + pq.push(c); + } + } + } + + // add up the total area of the intersecting pieces. + double area = 0.0; +#ifndef NDEBUG + double _t = -std::numeric_limits<double>::max(); +#endif + + while (! pq.empty()) + { + c = pq.top(); pq.pop(); +#ifndef NDEBUG + assert(_t <= c.m_t); + _t = c.m_t; +#endif + + // needed in case two consecutive points have the same intersection time. + if (c.m_t > tmin) area += x.getAreaInTime(Tools::Interval(tmin, c.m_t)); + + if (c.m_boundary == 0) + { + x.m_pLow[c.m_dimension] = c.m_to->m_pLow[c.m_dimension]; + x.m_pVLow[c.m_dimension] = c.m_to->m_pVLow[c.m_dimension]; + } + else + { + x.m_pHigh[c.m_dimension] = c.m_to->m_pHigh[c.m_dimension]; + x.m_pVHigh[c.m_dimension] = c.m_to->m_pVHigh[c.m_dimension]; + } + + tmin = c.m_t; + } + + // ... and the last piece + if (tmax > tmin) area += x.getAreaInTime(Tools::Interval(tmin, tmax)); + + return area; +} + +// +// IObject interface +// +MovingRegion* MovingRegion::clone() +{ + return new MovingRegion(*this); +} + +// +// ISerializable interface +// +uint32_t MovingRegion::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + 4 * m_dimension * sizeof(double)); +} + +void MovingRegion::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pHigh, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pVLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pVHigh, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void MovingRegion::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, m_pLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pHigh, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pVLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pVHigh, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IEvolvingShape interface +// +void MovingRegion::getVMBR(Region& out) const +{ + out.makeDimension(m_dimension); + memcpy(out.m_pLow, m_pVLow, m_dimension * sizeof(double)); + memcpy(out.m_pHigh, m_pVHigh, m_dimension * sizeof(double)); +} + +void MovingRegion::getMBRAtTime(double t, Region& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + out.m_pLow[cDim] = getLow(cDim, t); + out.m_pHigh[cDim] = getHigh(cDim, t); + } +} + +// +// ITimeShape interface +// +double MovingRegion::getAreaInTime() const +{ + return getAreaInTime(*this); +} + +// this computes the area/volume/etc. swept by the Region in time. +double MovingRegion::getAreaInTime(const IInterval& ivI) const +{ + double tmin = std::max(ivI.getLowerBound(), m_startTime); + double tmax = std::min(ivI.getUpperBound(), m_endTime); + + assert(tmin > -std::numeric_limits<double>::max()); + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin <= tmax); + + if (tmin >= tmax - std::numeric_limits<double>::epsilon() && + tmin <= tmax + std::numeric_limits<double>::epsilon()) + return 0.0; + + double dx1, dx2, dx3; + double dv1, dv2, dv3; + double H = tmax - tmin; + + if (m_dimension == 3) + { + dx3 = getExtrapolatedHigh(2, tmin) - getExtrapolatedLow(2, tmin); + dv3 = getVHigh(2) - getVLow(2); + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return + H * dx1 * dx2 * dx3 + H * H * (dx1 * dx2 * dv3 + (dx1 * dv2 + dv1 * dx2) * dx3) / 2.0 + + H * H * H * ((dx1 * dv2 + dv1 * dx2) * dv3 + dv1 * dv2 * dx3) / 3.0 + H * H * H * H * dv1 * dv2 * dv3 / 4.0; + } + else if (m_dimension == 2) + { + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return H * dx1 * dx2 + H * H * (dx1 * dv2 + dv1 * dx2) / 2.0 + H * H * H * dv1 * dv2 / 3.0; + } + else if (m_dimension == 1) + { + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return H * dx1 + H * H * dv1 / 2.0; + } + else + { + throw Tools::NotSupportedException("getAreaInTime: unsupported dimensionality."); + } +} + +double MovingRegion::getIntersectingAreaInTime(const ITimeShape& r) const +{ + return getIntersectingAreaInTime(r, r); +} + +double MovingRegion::getIntersectingAreaInTime(const IInterval& ivI, const ITimeShape& in) const +{ + const MovingRegion* pr = dynamic_cast<const MovingRegion*>(&in); + if (pr != 0) return getIntersectingAreaInTime(*pr); + + throw Tools::IllegalStateException("getIntersectingAreaInTime: Not implemented yet!"); +} + +void MovingRegion::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pLow[cIndex] = std::numeric_limits<double>::max(); + m_pHigh[cIndex] = -std::numeric_limits<double>::max(); + m_pVLow[cIndex] = std::numeric_limits<double>::max(); + m_pVHigh[cIndex] = -std::numeric_limits<double>::max(); + } + + m_startTime = -std::numeric_limits<double>::max(); + m_endTime = std::numeric_limits<double>::max(); +} + +void MovingRegion::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + m_dimension = dimension; + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const MovingRegion& r) +{ + uint32_t i; + + os << "Low: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pLow[i] << " "; + } + + os << ", High: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pHigh[i] << " "; + } + + os << "VLow: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pVLow[i] << " "; + } + + os << ", VHigh: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pVHigh[i] << " "; + } + + os << ", Start: " << r.m_startTime << ", End: " << r.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Point.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Point.cc.svn-base new file mode 100644 index 000000000..8c36c1123 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Point.cc.svn-base @@ -0,0 +1,262 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +Point::Point() + : m_dimension(0), m_pCoords(0) +{ +} + +Point::Point(const double* pCoords, uint32_t dimension) + : m_dimension(dimension) +{ + // no need to initialize m_pCoords to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pCoords = new double[m_dimension]; + memcpy(m_pCoords, pCoords, m_dimension * sizeof(double)); +} + +Point::Point(const Point& p) + : m_dimension(p.m_dimension) +{ + // no need to initialize m_pCoords to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pCoords = new double[m_dimension]; + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); +} + +Point::~Point() +{ + delete[] m_pCoords; +} + +Point& Point::operator=(const Point& p) +{ + if (this != &p) + { + makeDimension(p.m_dimension); + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + } + + return *this; +} + +bool Point::operator==(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Point::operator==: Points have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pCoords[i] < p.m_pCoords[i] - std::numeric_limits<double>::epsilon() || + m_pCoords[i] > p.m_pCoords[i] + std::numeric_limits<double>::epsilon()) return false; + } + + return true; +} + +// +// IObject interface +// +Point* Point::clone() +{ + return new Point(*this); +} + +// +// ISerializable interface +// +uint32_t Point::getByteArraySize() +{ + return (sizeof(uint32_t) + m_dimension * sizeof(double)); +} + +void Point::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + makeDimension(dimension); + memcpy(m_pCoords, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void Point::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, m_pCoords, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IShape interface +// +bool Point::intersectsShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->containsPoint(*this); + } + + throw Tools::IllegalStateException( + "Point::intersectsShape: Not implemented yet!" + ); +} + +bool Point::containsShape(const IShape& s) const +{ + return false; +} + +bool Point::touchesShape(const IShape& s) const +{ + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) + { + if (*this == *ppt) return true; + return false; + } + + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->touchesPoint(*this); + } + + throw Tools::IllegalStateException( + "Point::touchesShape: Not implemented yet!" + ); +} + +void Point::getCenter(Point& out) const +{ + out = *this; +} + +uint32_t Point::getDimension() const +{ + return m_dimension; +} + +void Point::getMBR(Region& out) const +{ + out = Region(m_pCoords, m_pCoords, m_dimension); +} + +double Point::getArea() const +{ + return 0.0; +} + +double Point::getMinimumDistance(const IShape& s) const +{ + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) + { + return getMinimumDistance(*ppt); + } + + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->getMinimumDistance(*this); + } + + throw Tools::IllegalStateException( + "Point::getMinimumDistance: Not implemented yet!" + ); +} + +double Point::getMinimumDistance(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Point::getMinimumDistance: Shapes have different number of dimensions." + ); + + double ret = 0.0; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + ret += std::pow(m_pCoords[cDim] - p.m_pCoords[cDim], 2.0); + } + + return std::sqrt(ret); +} + +double Point::getCoordinate(uint32_t index) const +{ + if (index < 0 || index >= m_dimension) + throw Tools::IndexOutOfBoundsException(index); + + return m_pCoords[index]; +} + +void Point::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pCoords[cIndex] = std::numeric_limits<double>::max(); + } +} + +void Point::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pCoords; + + // remember that this is not a constructor. The object will be destructed normally if + // something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state. + m_pCoords = 0; + + m_dimension = dimension; + m_pCoords = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const Point& pt) +{ + for (uint32_t cDim = 0; cDim < pt.m_dimension; ++cDim) + { + os << pt.m_pCoords[cDim] << " "; + } + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Region.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Region.cc.svn-base new file mode 100644 index 000000000..8db029831 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/Region.cc.svn-base @@ -0,0 +1,554 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../../include/SpatialIndex.h" + +#include <cstring> +#include <cmath> +#include <limits> + +using namespace SpatialIndex; + +Region::Region() + : m_dimension(0), m_pLow(0), m_pHigh(0) +{ +} + +Region::Region(const double* pLow, const double* pHigh, uint32_t dimension) +{ + initialize(pLow, pHigh, dimension); +} + +Region::Region(const Point& low, const Point& high) +{ + if (low.m_dimension != high.m_dimension) + throw Tools::IllegalArgumentException( + "Region::Region: arguments have different number of dimensions." + ); + + initialize(low.m_pCoords, high.m_pCoords, low.m_dimension); +} + +Region::Region(const Region& r) +{ + initialize(r.m_pLow, r.m_pHigh, r.m_dimension); +} + +void Region::initialize(const double* pLow, const double* pHigh, uint32_t dimension) +{ + m_pLow = 0; + m_dimension = dimension; + +#ifndef NDEBUG + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if ((pLow[cDim] > pHigh[cDim])) + { + // check for infinitive region + if (!(pLow[cDim] == std::numeric_limits<double>::max() || + pHigh[cDim] == -std::numeric_limits<double>::max() )) + throw Tools::IllegalArgumentException( + "Region::initialize: Low point has larger coordinates than High point." + " Neither point is infinity." + ); + } + } +#endif + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + throw; + } + + memcpy(m_pLow, pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, pHigh, m_dimension * sizeof(double)); +} + +Region::~Region() +{ + delete[] m_pLow; + delete[] m_pHigh; +} + +Region& Region::operator=(const Region& r) +{ + if(this != &r) + { + makeDimension(r.m_dimension); + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + } + + return *this; +} + +bool Region::operator==(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::operator==: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pLow[i] < r.m_pLow[i] - std::numeric_limits<double>::epsilon() || + m_pLow[i] > r.m_pLow[i] + std::numeric_limits<double>::epsilon() || + m_pHigh[i] < r.m_pHigh[i] - std::numeric_limits<double>::epsilon() || + m_pHigh[i] > r.m_pHigh[i] + std::numeric_limits<double>::epsilon()) + return false; + } + return true; +} + +// +// IObject interface +// +Region* Region::clone() +{ + return new Region(*this); +} + +// +// ISerializable interface +// +uint32_t Region::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * m_dimension * sizeof(double)); +} + +void Region::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + makeDimension(dimension); + memcpy(m_pLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pHigh, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void Region::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, m_pLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pHigh, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IShape interface +// +bool Region::intersectsShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return intersectsRegion(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return containsPoint(*ppt); + + throw Tools::IllegalStateException( + "Region::intersectsShape: Not implemented yet!" + ); +} + +bool Region::containsShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return containsRegion(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return containsPoint(*ppt); + + throw Tools::IllegalStateException( + "Region::containsShape: Not implemented yet!" + ); +} + +bool Region::touchesShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return touchesRegion(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return touchesPoint(*ppt); + + throw Tools::IllegalStateException( + "Region::touchesShape: Not implemented yet!" + ); +} + +void Region::getCenter(Point& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t i = 0; i < m_dimension; ++i) + { + out.m_pCoords[i] = (m_pLow[i] + m_pHigh[i]) / 2.0; + } +} + +uint32_t Region::getDimension() const +{ + return m_dimension; +} + +void Region::getMBR(Region& out) const +{ + out = *this; +} + +double Region::getArea() const +{ + double area = 1.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + area *= m_pHigh[i] - m_pLow[i]; + } + + return area; +} + +double Region::getMinimumDistance(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return getMinimumDistance(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return getMinimumDistance(*ppt); + + throw Tools::IllegalStateException( + "Region::getMinimumDistance: Not implemented yet!" + ); +} + +bool Region::intersectsRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::intersectsRegion: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (m_pLow[i] > r.m_pHigh[i] || m_pHigh[i] < r.m_pLow[i]) return false; + } + return true; +} + +bool Region::containsRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::containsRegion: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (m_pLow[i] > r.m_pLow[i] || m_pHigh[i] < r.m_pHigh[i]) return false; + } + return true; +} + +bool Region::touchesRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::touchesRegion: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + (m_pLow[i] >= r.m_pLow[i] + std::numeric_limits<double>::epsilon() && + m_pLow[i] <= r.m_pLow[i] - std::numeric_limits<double>::epsilon()) || + (m_pHigh[i] >= r.m_pHigh[i] + std::numeric_limits<double>::epsilon() && + m_pHigh[i] <= r.m_pHigh[i] - std::numeric_limits<double>::epsilon())) + return false; + } + return true; +} + +double Region::getMinimumDistance(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getMinimumDistance: Regions have different number of dimensions." + ); + + double ret = 0.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + double x = 0.0; + + if (r.m_pHigh[i] < m_pLow[i]) + { + x = std::abs(r.m_pHigh[i] - m_pLow[i]); + } + else if (m_pHigh[i] < r.m_pLow[i]) + { + x = std::abs(r.m_pLow[i] - m_pHigh[i]); + } + + ret += x * x; + } + + return std::sqrt(ret); +} + +bool Region::containsPoint(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::containsPoint: Point has different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (m_pLow[i] > p.getCoordinate(i) || m_pHigh[i] < p.getCoordinate(i)) return false; + } + return true; +} + +bool Region::touchesPoint(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::touchesPoint: Point has different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + (m_pLow[i] >= p.getCoordinate(i) - std::numeric_limits<double>::epsilon() && + m_pLow[i] <= p.getCoordinate(i) + std::numeric_limits<double>::epsilon()) || + (m_pHigh[i] >= p.getCoordinate(i) - std::numeric_limits<double>::epsilon() && + m_pHigh[i] <= p.getCoordinate(i) + std::numeric_limits<double>::epsilon())) + return true; + } + return false; +} + +double Region::getMinimumDistance(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getMinimumDistance: Point has different number of dimensions." + ); + + double ret = 0.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (p.getCoordinate(i) < m_pLow[i]) + { + ret += std::pow(m_pLow[i] - p.getCoordinate(i), 2.0); + } + else if (p.getCoordinate(i) > m_pHigh[i]) + { + ret += std::pow(p.getCoordinate(i) - m_pHigh[i], 2.0); + } + } + + return std::sqrt(ret); +} + +Region Region::getIntersectingRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getIntersectingRegion: Regions have different number of dimensions." + ); + + Region ret; + ret.makeInfinite(m_dimension); + + // check for intersection. + // marioh: avoid function call since this is called billions of times. + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (m_pLow[cDim] > r.m_pHigh[cDim] || m_pHigh[cDim] < r.m_pLow[cDim]) return ret; + } + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + ret.m_pLow[cDim] = std::max(m_pLow[cDim], r.m_pLow[cDim]); + ret.m_pHigh[cDim] = std::min(m_pHigh[cDim], r.m_pHigh[cDim]); + } + + return ret; +} + +double Region::getIntersectingArea(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getIntersectingArea: Regions have different number of dimensions." + ); + + double ret = 1.0; + double f1, f2; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (m_pLow[cDim] > r.m_pHigh[cDim] || m_pHigh[cDim] < r.m_pLow[cDim]) return 0.0; + + f1 = std::max(m_pLow[cDim], r.m_pLow[cDim]); + f2 = std::min(m_pHigh[cDim], r.m_pHigh[cDim]); + ret *= f2 - f1; + } + + return ret; +} + +/* + * Returns the margin of a region. It is calcuated as the sum of 2^(d-1) * width, in each dimension. + * It is actually the sum of all edges, no matter what the dimensionality is. +*/ +double Region::getMargin() const +{ + double mul = std::pow(2.0, static_cast<double>(m_dimension) - 1.0); + double margin = 0.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + margin += (m_pHigh[i] - m_pLow[i]) * mul; + } + + return margin; +} + +void Region::combineRegion(const Region& r) +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::combineRegion: Region has different number of dimensions." + ); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(m_pLow[cDim], r.m_pLow[cDim]); + m_pHigh[cDim] = std::max(m_pHigh[cDim], r.m_pHigh[cDim]); + } +} + +void Region::combinePoint(const Point& p) +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::combinePoint: Point has different number of dimensions." + ); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(m_pLow[cDim], p.m_pCoords[cDim]); + m_pHigh[cDim] = std::max(m_pHigh[cDim], p.m_pCoords[cDim]); + } +} + +void Region::getCombinedRegion(Region& out, const Region& in) const +{ + if (m_dimension != in.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getCombinedRegion: Regions have different number of dimensions." + ); + + out = *this; + out.combineRegion(in); +} + +double Region::getLow(uint32_t index) const +{ + if (index < 0 || index >= m_dimension) + throw Tools::IndexOutOfBoundsException(index); + + return m_pLow[index]; +} + +double Region::getHigh(uint32_t index) const +{ + if (index < 0 || index >= m_dimension) + throw Tools::IndexOutOfBoundsException(index); + + return m_pHigh[index]; +} + +void Region::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pLow[cIndex] = std::numeric_limits<double>::max(); + m_pHigh[cIndex] = -std::numeric_limits<double>::max(); + } +} + +void Region::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pLow; + delete[] m_pHigh; + + // remember that this is not a constructor. The object will be destructed normally if + // something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state. + m_pLow = 0; m_pHigh = 0; + + m_dimension = dimension; + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const Region& r) +{ + uint32_t i; + + os << "Low: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pLow[i] << " "; + } + + os << ", High: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pHigh[i] << " "; + } + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/SpatialIndexImpl.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/SpatialIndexImpl.cc.svn-base new file mode 100644 index 000000000..9d2bd11aa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/SpatialIndexImpl.cc.svn-base @@ -0,0 +1,93 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "SpatialIndexImpl.h" + +#include "../rtree/RTree.h" +#include "../mvrtree/MVRTree.h" +#include "../tprtree/TPRTree.h" + +SpatialIndex::InvalidPageException::InvalidPageException(id_type id) +{ + std::ostringstream s; + s << "Unknown page id " << id; + m_error = s.str(); +} + +std::string SpatialIndex::InvalidPageException::what() +{ + return "InvalidPageException: " + m_error; +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const ISpatialIndex& i) +{ + const SpatialIndex::RTree::RTree* pRTree = dynamic_cast<const SpatialIndex::RTree::RTree*>(&i); + if (pRTree != 0) + { + os << *pRTree; + return os; + } + + const SpatialIndex::MVRTree::MVRTree* pMVRTree = dynamic_cast<const SpatialIndex::MVRTree::MVRTree*>(&i); + if (pMVRTree != 0) + { + os << *pMVRTree; + return os; + } + + const SpatialIndex::TPRTree::TPRTree* pTPRTree = dynamic_cast<const SpatialIndex::TPRTree::TPRTree*>(&i); + if (pTPRTree != 0) + { + os << *pTPRTree; + return os; + } + + std::cerr << "ISpatialIndex operator<<: Not implemented yet for this index type." << std::endl; + return os; +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const IStatistics& s) +{ + const SpatialIndex::RTree::Statistics* pRTreeStats = dynamic_cast<const SpatialIndex::RTree::Statistics*>(&s); + if (pRTreeStats != 0) + { + os << *pRTreeStats; + return os; + } + + const SpatialIndex::MVRTree::Statistics* pMVRTreeStats = dynamic_cast<const SpatialIndex::MVRTree::Statistics*>(&s); + if (pMVRTreeStats != 0) + { + os << * pMVRTreeStats; + return os; + } + + const SpatialIndex::TPRTree::Statistics* pTPRTreeStats = dynamic_cast<const SpatialIndex::TPRTree::Statistics*>(&s); + if (pTPRTreeStats != 0) + { + os << * pTPRTreeStats; + return os; + } + + std::cerr << "IStatistics operator<<: Not implemented yet for this index type." << std::endl; + return os; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/SpatialIndexImpl.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/SpatialIndexImpl.h.svn-base new file mode 100644 index 000000000..5a24bbc6e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/SpatialIndexImpl.h.svn-base @@ -0,0 +1,32 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +typedef Tools::PoolPointer<Region> RegionPtr; +typedef Tools::PoolPointer<Point> PointPtr; +typedef Tools::PoolPointer<TimeRegion> TimeRegionPtr; +typedef Tools::PoolPointer<MovingRegion> MovingRegionPtr; + diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/TimePoint.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/TimePoint.cc.svn-base new file mode 100644 index 000000000..d860a0168 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/TimePoint.cc.svn-base @@ -0,0 +1,297 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +TimePoint::TimePoint() + : Point(), m_startTime(-std::numeric_limits<double>::max()), m_endTime(std::numeric_limits<double>::max()) +{ +} + +TimePoint::TimePoint(const double* pCoords, const IInterval& ti, uint32_t dimension) + : Point(pCoords, dimension), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimePoint::TimePoint(const double* pCoords, double tStart, double tEnd, uint32_t dimension) + : Point(pCoords, dimension), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimePoint::TimePoint(const Point& p, const IInterval& ti) + : Point(p), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimePoint::TimePoint(const Point& p, double tStart, double tEnd) + : Point(p), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimePoint::TimePoint(const TimePoint& p) + : m_startTime(p.m_startTime), m_endTime(p.m_endTime) +{ + m_dimension = p.m_dimension; + + m_pCoords = new double[m_dimension]; + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); +} + +TimePoint::~TimePoint() +{ +} + +TimePoint& TimePoint::operator=(const TimePoint& p) +{ + if (this != &p) + { + makeDimension(p.m_dimension); + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + m_startTime = p.m_startTime; + m_endTime = p.m_endTime; + } + + return *this; +} + +bool TimePoint::operator==(const TimePoint& p) const +{ + if ( + m_startTime < p.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > p.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < p.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > p.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if ( + m_pCoords[cDim] < p.m_pCoords[cDim] - std::numeric_limits<double>::epsilon() || + m_pCoords[cDim] > p.m_pCoords[cDim] + std::numeric_limits<double>::epsilon()) + return false; + } + + return true; +} + +// +// IObject interface +// +TimePoint* TimePoint::clone() +{ + return new TimePoint(*this); +} + +// +// ISerializable interface +// +uint32_t TimePoint::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + m_dimension * sizeof(double)); +} + +void TimePoint::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pCoords, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void TimePoint::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, m_pCoords, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// ITimeShape interface +// +bool TimePoint::intersectsShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return pr->containsPointInTime(*this); + + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimePoint::intersectsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimePoint::containsShapeInTime(const ITimeShape& in) const +{ + return false; +} + +bool TimePoint::containsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + return false; +} + +bool TimePoint::touchesShapeInTime(const ITimeShape& in) const +{ + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +bool TimePoint::touchesShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +double TimePoint::getAreaInTime() const +{ + return 0.0; +} + +double TimePoint::getAreaInTime(const IInterval& ivI) const +{ + return 0.0; +} + +double TimePoint::getIntersectingAreaInTime(const ITimeShape& r) const +{ + return 0.0; +} + +double TimePoint::getIntersectingAreaInTime(const IInterval& ivI, const ITimeShape& r) const +{ + return 0.0; +} + +// +// IInterval interface +// +Tools::IInterval& TimePoint::operator=(const Tools::IInterval& i) +{ + if (this != &i) + { + m_startTime = i.getLowerBound(); + m_endTime = i.getUpperBound(); + } + + return *this; +} + +double TimePoint::getLowerBound() const +{ + return m_startTime; +} + +double TimePoint::getUpperBound() const +{ + return m_endTime; +} + +void TimePoint::setBounds(double l, double h) +{ + assert(l <= h); + + m_startTime = l; + m_endTime = h; +} + +bool TimePoint::intersectsInterval(const IInterval& ti) const +{ + return intersectsInterval(ti.getIntervalType(), ti.getLowerBound(), ti.getUpperBound()); +} + +bool TimePoint::intersectsInterval(Tools::IntervalType t, const double start, const double end) const +{ + //if (m_startTime != start && + // (m_startTime >= end || m_endTime <= start)) return false; + if (m_startTime >= end || m_endTime <= start) return false; + + return true; +} + +bool TimePoint::containsInterval(const IInterval& ti) const +{ + if (m_startTime <= ti.getLowerBound() && m_endTime >= ti.getUpperBound()) return true; + return false; +} + +Tools::IntervalType TimePoint::getIntervalType() const +{ + return Tools::IT_RIGHTOPEN; +} + +void TimePoint::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pCoords[cIndex] = std::numeric_limits<double>::max(); + } + + m_startTime = std::numeric_limits<double>::max(); + m_endTime = -std::numeric_limits<double>::max(); +} + +void TimePoint::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + m_dimension = dimension; + + delete[] m_pCoords; + m_pCoords = 0; + + m_pCoords = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const TimePoint& pt) +{ + uint32_t i; + + for (i = 0; i < pt.m_dimension; ++i) + { + os << pt.m_pCoords[i] << " "; + } + + os << ", Start: " << pt.m_startTime << ", End: " << pt.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/TimeRegion.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/TimeRegion.cc.svn-base new file mode 100644 index 000000000..00d575223 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/.svn/text-base/TimeRegion.cc.svn-base @@ -0,0 +1,419 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../../include/SpatialIndex.h" + +#include <cstring> +#include <limits> + +using namespace SpatialIndex; + +TimeRegion::TimeRegion() + : Region(), m_startTime(-std::numeric_limits<double>::max()), m_endTime(std::numeric_limits<double>::max()) +{ +} + +TimeRegion::TimeRegion(const double* pLow, const double* pHigh, const IInterval& ti, uint32_t dimension) + : Region(pLow, pHigh, dimension), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimeRegion::TimeRegion(const double* pLow, const double* pHigh, double tStart, double tEnd, uint32_t dimension) + : Region(pLow, pHigh, dimension), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimeRegion::TimeRegion(const Point& low, const Point& high, const IInterval& ti) + : Region(low, high), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimeRegion::TimeRegion(const Point& low, const Point& high, double tStart, double tEnd) + : Region(low, high), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimeRegion::TimeRegion(const Region& r, const IInterval& ti) + : Region(r), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimeRegion::TimeRegion(const Region& r, double tStart, double tEnd) + : Region(r), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimeRegion::TimeRegion(const TimePoint& low, const TimePoint& high) + : Region((Point&) low, (Point&) high), m_startTime(low.m_startTime), m_endTime(high.m_endTime) +{ +} + +TimeRegion::TimeRegion(const TimeRegion& r) + : m_startTime(r.m_startTime), m_endTime(r.m_endTime) +{ + m_dimension = r.m_dimension; + m_pLow = 0; + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + throw; + } + + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); +} + +TimeRegion::~TimeRegion() +{ +} + +TimeRegion& TimeRegion::operator=(const TimeRegion& r) +{ + if(this != &r) + { + makeDimension(r.m_dimension); + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + + m_startTime = r.m_startTime; + m_endTime = r.m_endTime; + } + + return *this; +} + +bool TimeRegion::operator==(const TimeRegion& r) const +{ + if (m_startTime < r.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > r.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < r.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > r.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pLow[i] < r.m_pLow[i] - std::numeric_limits<double>::epsilon() || + m_pLow[i] > r.m_pLow[i] + std::numeric_limits<double>::epsilon() || + m_pHigh[i] < r.m_pHigh[i] - std::numeric_limits<double>::epsilon() || + m_pHigh[i] > r.m_pHigh[i] + std::numeric_limits<double>::epsilon()) + return false; + } + return true; +} + +bool TimeRegion::intersectsRegionInTime(const TimeRegion& r) const +{ + // they should just intersect in time. + // check if they intersect in time first. + // the first check is needed for the following case: + // m_endTime == m_startTime == r.m_startTime. + // For open ended intervals this should be considered as an intersection + // (takes care of degenarate intervals) + //if (m_startTime != r.m_startTime && + // (m_startTime >= r.m_endTime || m_endTime <= r.m_startTime)) + if (! intersectsInterval(r)) return false; + return Region::intersectsRegion(r); +} + +bool TimeRegion::containsRegionInTime(const TimeRegion& r) const +{ + // it should be contained in time. + if (! containsInterval(r)) return false; + return Region::containsRegion(r); +} + +bool TimeRegion::touchesRegionInTime(const TimeRegion& r) const +{ + // they should just intersect in time. + //if (m_startTime != r.m_startTime && + // (m_startTime >= r.m_endTime || m_endTime <= r.m_startTime)) + if (!intersectsInterval(r)) return false; + return Region::touchesRegion(r); +} + +bool TimeRegion::containsPointInTime(const TimePoint& p) const +{ + // it should be contained in time. + //if (p.m_startTime < m_startTime || p.m_endTime > m_endTime) return false; + if (containsInterval(p)) return false; + return Region::containsPoint(p); +} + +bool TimeRegion::touchesPointInTime(const TimePoint& p) const +{ + // they should just intersect in time. + //if (m_startTime != p.m_startTime && + // (m_startTime >= p.m_endTime || m_endTime <= p.m_startTime)) + if (intersectsInterval(p)) return false; + return Region::touchesPoint(p); +} + +void TimeRegion::combineRegionInTime(const TimeRegion& r) +{ + Region::combineRegion(r); + + m_startTime = std::min(m_startTime, r.m_startTime); + m_endTime = std::max(m_endTime, r.m_endTime); +} + +void TimeRegion::getCombinedRegionInTime(TimeRegion& out, const TimeRegion& in) const +{ + Region::getCombinedRegion(out, in); + + out.m_startTime = std::min(m_startTime, in.m_startTime); + out.m_endTime = std::max(m_endTime, in.m_endTime); +} + +// +// IObject interface +// +TimeRegion* TimeRegion::clone() +{ + return new TimeRegion(*this); +} + +// +// ISerializable interface +// +uint32_t TimeRegion::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + 2 * m_dimension * sizeof(double)); +} + +void TimeRegion::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pHigh, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void TimeRegion::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, m_pLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pHigh, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// ITimeShape interface +// +bool TimeRegion::intersectsShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return intersectsRegionInTime(*pr); + + const TimePoint* ppt = dynamic_cast<const TimePoint*>(&in); + if (ppt != 0) return containsPointInTime(*ppt); + + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::intersectsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::containsShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return containsRegionInTime(*pr); + + const TimePoint* ppt = dynamic_cast<const TimePoint*>(&in); + if (ppt != 0) return containsPointInTime(*ppt); + + throw Tools::IllegalStateException("containsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::containsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("containsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::touchesShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return touchesRegionInTime(*pr); + + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::touchesShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +double TimeRegion::getAreaInTime() const +{ + throw Tools::IllegalStateException("getAreaInTime: Not implemented yet!"); +} + +double TimeRegion::getAreaInTime(const IInterval& ivI) const +{ + throw Tools::IllegalStateException("getAreaInTime: Not implemented yet!"); +} + +double TimeRegion::getIntersectingAreaInTime(const ITimeShape& r) const +{ + throw Tools::IllegalStateException("getIntersectingAreaInTime: Not implemented yet!"); +} + +double TimeRegion::getIntersectingAreaInTime(const IInterval& ivI, const ITimeShape& r) const +{ + throw Tools::IllegalStateException("getIntersectingAreaInTime: Not implemented yet!"); +} + +// +// IInterval interface +// +Tools::IInterval& TimeRegion::operator=(const Tools::IInterval& i) +{ + if (this != &i) + { + m_startTime = i.getLowerBound(); + m_endTime = i.getUpperBound(); + } + + return *this; +} + +double TimeRegion::getLowerBound() const +{ + return m_startTime; +} + +double TimeRegion::getUpperBound() const +{ + return m_endTime; +} + +void TimeRegion::setBounds(double l, double h) +{ + assert(m_startTime <= m_endTime); + + m_startTime = l; + m_endTime = h; +} + +bool TimeRegion::intersectsInterval(const IInterval& ti) const +{ + return intersectsInterval(ti.getIntervalType(), ti.getLowerBound(), ti.getUpperBound()); +} + +bool TimeRegion::intersectsInterval(Tools::IntervalType t, const double start, const double end) const +{ + //if (m_startTime != start && + // (m_startTime >= end || m_endTime <= start)) return false; + // this will not work for degenarate intervals. + if (m_startTime >= end || m_endTime <= start) return false; + + return true; +} + +bool TimeRegion::containsInterval(const IInterval& ti) const +{ + if (m_startTime <= ti.getLowerBound() && m_endTime >= ti.getUpperBound()) return true; + return false; +} + +Tools::IntervalType TimeRegion::getIntervalType() const +{ + return Tools::IT_RIGHTOPEN; +} + +void TimeRegion::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pLow[cIndex] = std::numeric_limits<double>::max(); + m_pHigh[cIndex] = -std::numeric_limits<double>::max(); + } + + m_startTime = std::numeric_limits<double>::max(); + m_endTime = -std::numeric_limits<double>::max(); +} + +void TimeRegion::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + m_dimension = dimension; + + delete[] m_pLow; + delete[] m_pHigh; + m_pLow = 0; m_pHigh = 0; + + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const TimeRegion& r) +{ + uint32_t i; + + os << "Low: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pLow[i] << " "; + } + + os << ", High: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pHigh[i] << " "; + } + + os << ", Start: " << r.m_startTime << ", End: " << r.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/LineSegment.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/LineSegment.cc new file mode 100644 index 000000000..1653f15da --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/LineSegment.cc @@ -0,0 +1,388 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +LineSegment::LineSegment() + : m_dimension(0), m_pStartPoint(0), m_pEndPoint(0) +{ +} + +LineSegment::LineSegment(const double* pStartPoint, const double* pEndPoint, uint32_t dimension) + : m_dimension(dimension) +{ + // no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + memcpy(m_pStartPoint, pStartPoint, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, pEndPoint, m_dimension * sizeof(double)); +} + +LineSegment::LineSegment(const Point& startPoint, const Point& endPoint) + : m_dimension(startPoint.m_dimension) +{ + if (startPoint.m_dimension != endPoint.m_dimension) + throw Tools::IllegalArgumentException( + "LineSegment::LineSegment: Points have different dimensionalities." + ); + + // no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + memcpy(m_pStartPoint, startPoint.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, endPoint.m_pCoords, m_dimension * sizeof(double)); +} + +LineSegment::LineSegment(const LineSegment& l) + : m_dimension(l.m_dimension) +{ + // no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + memcpy(m_pStartPoint, l.m_pStartPoint, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, l.m_pEndPoint, m_dimension * sizeof(double)); +} + +LineSegment::~LineSegment() +{ + delete[] m_pStartPoint; + delete[] m_pEndPoint; +} + +LineSegment& LineSegment::operator=(const LineSegment& l) +{ + if (this != &l) + { + makeDimension(l.m_dimension); + memcpy(m_pStartPoint, l.m_pStartPoint, m_dimension * sizeof(double)); + memcpy(m_pEndPoint, l.m_pEndPoint, m_dimension * sizeof(double)); + } + + return *this; +} + +bool LineSegment::operator==(const LineSegment& l) const +{ + if (m_dimension != l.m_dimension) + throw Tools::IllegalArgumentException( + "LineSegment::operator==: LineSegments have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pStartPoint[i] < l.m_pStartPoint[i] - std::numeric_limits<double>::epsilon() || + m_pStartPoint[i] > l.m_pStartPoint[i] + std::numeric_limits<double>::epsilon()) return false; + + if ( + m_pEndPoint[i] < l.m_pEndPoint[i] - std::numeric_limits<double>::epsilon() || + m_pEndPoint[i] > l.m_pEndPoint[i] + std::numeric_limits<double>::epsilon()) return false; + } + + return true; +} + +// +// IObject interface +// +LineSegment* LineSegment::clone() +{ + return new LineSegment(*this); +} + +// +// ISerializable interface +// +uint32_t LineSegment::getByteArraySize() +{ + return (sizeof(uint32_t) + m_dimension * sizeof(double) * 2); +} + +void LineSegment::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + makeDimension(dimension); + memcpy(m_pStartPoint, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pEndPoint, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void LineSegment::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, m_pStartPoint, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pEndPoint, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IShape interface +// +bool LineSegment::intersectsShape(const IShape& s) const +{ + throw Tools::IllegalStateException( + "LineSegment::intersectsShape: Not implemented yet!" + ); +} + +bool LineSegment::containsShape(const IShape& s) const +{ + return false; +} + +bool LineSegment::touchesShape(const IShape& s) const +{ + throw Tools::IllegalStateException( + "LineSegment::touchesShape: Not implemented yet!" + ); +} + +void LineSegment::getCenter(Point& out) const +{ + double* coords = new double[m_dimension]; + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + coords[cDim] = + (std::abs(m_pStartPoint[cDim] - m_pEndPoint[cDim]) / 2.0) + + std::min(m_pStartPoint[cDim], m_pEndPoint[cDim]); + } + + out = Point(coords, m_dimension); + delete[] coords; +} + +uint32_t LineSegment::getDimension() const +{ + return m_dimension; +} + +void LineSegment::getMBR(Region& out) const +{ + double* low = new double[m_dimension]; + double* high = new double[m_dimension]; + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + low[cDim] = std::min(m_pStartPoint[cDim], m_pEndPoint[cDim]); + high[cDim] = std::max(m_pStartPoint[cDim], m_pEndPoint[cDim]); + } + + out = Region(low, high, m_dimension); + delete[] low; + delete[] high; +} + +double LineSegment::getArea() const +{ + return 0.0; +} + +double LineSegment::getMinimumDistance(const IShape& s) const +{ + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) + { + return getMinimumDistance(*ppt); + } + +/* + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->getMinimumDistance(*this); + } +*/ + + throw Tools::IllegalStateException( + "LineSegment::getMinimumDistance: Not implemented yet!" + ); +} + +double LineSegment::getMinimumDistance(const Point& p) const +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getMinimumDistance: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getMinimumDistance: Distance for high dimensional spaces not supported!" + ); + + if (m_pEndPoint[0] >= m_pStartPoint[0] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[0] <= m_pStartPoint[0] + std::numeric_limits<double>::epsilon()) return std::abs(p.m_pCoords[0] - m_pStartPoint[0]); + + if (m_pEndPoint[1] >= m_pStartPoint[1] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[1] <= m_pStartPoint[1] + std::numeric_limits<double>::epsilon()) return std::abs(p.m_pCoords[1] - m_pStartPoint[1]); + + double x1 = m_pStartPoint[0]; + double x2 = m_pEndPoint[0]; + double x0 = p.m_pCoords[0]; + double y1 = m_pStartPoint[1]; + double y2 = m_pEndPoint[1]; + double y0 = p.m_pCoords[1]; + + return std::abs((x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1)) / (std::sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))); +} + +// assuming moving from start to end, positive distance is from right hand side. +double LineSegment::getRelativeMinimumDistance(const Point& p) const +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMinimumDistance: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMinimumDistance: Distance for high dimensional spaces not supported!" + ); + + if (m_pEndPoint[0] >= m_pStartPoint[0] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[0] <= m_pStartPoint[0] + std::numeric_limits<double>::epsilon()) + { + if (m_pStartPoint[1] < m_pEndPoint[1]) return m_pStartPoint[0] - p.m_pCoords[0]; + if (m_pStartPoint[1] >= m_pEndPoint[1]) return p.m_pCoords[0] - m_pStartPoint[0]; + } + + if (m_pEndPoint[1] >= m_pStartPoint[1] - std::numeric_limits<double>::epsilon() && + m_pEndPoint[1] <= m_pStartPoint[1] + std::numeric_limits<double>::epsilon()) + { + if (m_pStartPoint[0] < m_pEndPoint[0]) return p.m_pCoords[1] - m_pStartPoint[1]; + if (m_pStartPoint[0] >= m_pEndPoint[0]) return m_pStartPoint[1] - p.m_pCoords[1]; + } + + double x1 = m_pStartPoint[0]; + double x2 = m_pEndPoint[0]; + double x0 = p.m_pCoords[0]; + double y1 = m_pStartPoint[1]; + double y2 = m_pEndPoint[1]; + double y0 = p.m_pCoords[1]; + + return ((x1 - x0) * (y2 - y1) - (x2 - x1) * (y1 - y0)) / (std::sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))); +} + +double LineSegment::getRelativeMaximumDistance(const Region& r) const +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMaximumDistance: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getRelativeMaximumDistance: Distance for high dimensional spaces not supported!" + ); + + // clockwise. + double d1 = getRelativeMinimumDistance(Point(r.m_pLow, 2)); + + double coords[2]; + coords[0] = r.m_pLow[0]; + coords[1] = r.m_pHigh[1]; + double d2 = getRelativeMinimumDistance(Point(coords, 2)); + + double d3 = getRelativeMinimumDistance(Point(r.m_pHigh, 2)); + + coords[0] = r.m_pHigh[0]; + coords[1] = r.m_pLow[1]; + double d4 = getRelativeMinimumDistance(Point(coords, 2)); + + return std::max(d1, std::max(d2, std::max(d3, d4))); +} + +double LineSegment::getAngleOfPerpendicularRay() +{ + if (m_dimension == 1) + throw Tools::NotSupportedException( + "LineSegment::getAngleOfPerpendicularRay: Use an Interval instead." + ); + + if (m_dimension != 2) + throw Tools::NotSupportedException( + "LineSegment::getAngleOfPerpendicularRay: Distance for high dimensional spaces not supported!" + ); + + if (m_pStartPoint[0] >= m_pEndPoint[0] - std::numeric_limits<double>::epsilon() && + m_pStartPoint[0] <= m_pEndPoint[0] + std::numeric_limits<double>::epsilon()) return 0.0; + + if (m_pStartPoint[1] >= m_pEndPoint[1] - std::numeric_limits<double>::epsilon() && + m_pStartPoint[1] <= m_pEndPoint[1] + std::numeric_limits<double>::epsilon()) return M_PI_2; + + return std::atan(-(m_pStartPoint[0] - m_pEndPoint[0]) / (m_pStartPoint[1] - m_pEndPoint[1])); +} + +void LineSegment::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pStartPoint[cIndex] = std::numeric_limits<double>::max(); + m_pEndPoint[cIndex] = std::numeric_limits<double>::max(); + } +} + +void LineSegment::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pStartPoint; + delete[] m_pEndPoint; + + // remember that this is not a constructor. The object will be destructed normally if + // something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state. + m_pStartPoint = 0; + m_pEndPoint = 0; + + m_dimension = dimension; + m_pStartPoint = new double[m_dimension]; + m_pEndPoint = new double[m_dimension]; + } +} + +std::ostream& operator<<(std::ostream& os, const LineSegment& l) +{ + for (uint32_t cDim = 0; cDim < l.m_dimension; ++cDim) + { + os << l.m_pStartPoint[cDim] << ", " << l.m_pEndPoint[cDim] << " "; + } + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Makefile.am new file mode 100644 index 000000000..6a0adc928 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Makefile.am @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = liblibrary.la +INCLUDES = -I../../include +liblibrary_la_SOURCES = Point.cc Region.cc LineSegment.cc MovingPoint.cc MovingRegion.cc TimePoint.cc TimeRegion.cc SpatialIndexImpl.cc SpatialIndexImpl.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/MovingPoint.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/MovingPoint.cc new file mode 100644 index 000000000..d3a33cb59 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/MovingPoint.cc @@ -0,0 +1,299 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +MovingPoint::MovingPoint() +{ +} + +MovingPoint::MovingPoint(const double* pCoords, const double* pVCoords, const IInterval& ti, uint32_t dimension) +{ + initialize(pCoords, pVCoords, ti.getLowerBound(), ti.getUpperBound(), dimension); +} + +MovingPoint::MovingPoint(const double* pCoords, const double* pVCoords, double tStart, double tEnd, uint32_t dimension) +{ + initialize(pCoords, pVCoords, tStart, tEnd, dimension); +} + +MovingPoint::MovingPoint(const Point& p, const Point& vp, const IInterval& ti) +{ + if (p.m_dimension != vp.m_dimension) throw Tools::IllegalArgumentException("MovingPoint: Points have different number of dimensions."); + + initialize(p.m_pCoords, vp.m_pCoords, ti.getLowerBound(), ti.getUpperBound(), p.m_dimension); +} + +MovingPoint::MovingPoint(const Point& p, const Point& vp, double tStart, double tEnd) +{ + if (p.m_dimension != vp.m_dimension) throw Tools::IllegalArgumentException("MovingPoint: Points have different number of dimensions."); + + initialize(p.m_pCoords, vp.m_pCoords, tStart, tEnd, p.m_dimension); +} + +MovingPoint::MovingPoint(const MovingPoint& p) +{ + m_startTime = p.m_startTime; + m_endTime = p.m_endTime; + m_pCoords = 0; + + m_dimension = p.m_dimension; + + try + { + m_pCoords = new double[m_dimension]; + m_pVCoords = new double[m_dimension]; + } + catch (...) + { + delete[] m_pCoords; + throw; + } + + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pVCoords, p.m_pVCoords, m_dimension * sizeof(double)); +} + +MovingPoint::~MovingPoint() +{ + delete[] m_pVCoords; +} + +void MovingPoint::initialize( + const double* pCoords, const double* pVCoords, + double tStart, double tEnd, uint32_t dimension) +{ + m_dimension = dimension; + m_startTime = tStart; + m_endTime = tEnd; + m_pCoords = 0; + + if (m_endTime <= m_startTime) throw Tools::IllegalArgumentException("MovingPoint: Cannot support degenerate time intervals."); + + try + { + m_pCoords = new double[m_dimension]; + m_pVCoords = new double[m_dimension]; + } + catch (...) + { + delete[] m_pCoords; + throw; + } + + // first store the point coordinates, than the point velocities. + memcpy(m_pCoords, pCoords, m_dimension * sizeof(double)); + memcpy(m_pVCoords, pVCoords, m_dimension * sizeof(double)); +} + +MovingPoint& MovingPoint::operator=(const MovingPoint& p) +{ + if (this != &p) + { + makeDimension(p.m_dimension); + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pVCoords, p.m_pVCoords, m_dimension * sizeof(double)); + + m_startTime = p.m_startTime; + m_endTime = p.m_endTime; + } + + return *this; +} + +bool MovingPoint::operator==(const MovingPoint& p) const +{ + if ( + m_startTime < p.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > p.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < p.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > p.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t cDim = 0; cDim < 2 * m_dimension; ++cDim) + { + if ( + m_pCoords[cDim] < p.m_pCoords[cDim] - std::numeric_limits<double>::epsilon() || + m_pCoords[cDim] > p.m_pCoords[cDim] + std::numeric_limits<double>::epsilon() || + m_pVCoords[cDim] < p.m_pVCoords[cDim] - std::numeric_limits<double>::epsilon() || + m_pVCoords[cDim] > p.m_pVCoords[cDim] + std::numeric_limits<double>::epsilon()) + return false; + } + + return true; +} + +double MovingPoint::getCoord(uint32_t d, double t) const +{ + if (d < 0 && d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + if (t >= m_endTime) return m_pCoords[d] + m_pVCoords[d] * (m_endTime - m_startTime); + else if (t <= m_startTime) return m_pCoords[d] + m_pVCoords[d] * m_startTime; + else return m_pCoords[d] + m_pVCoords[d] * (t - m_startTime); +} + +double MovingPoint::getProjectedCoord(uint32_t d, double t) const +{ + if (d < 0 && d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pCoords[d] + m_pVCoords[d] * (t - m_startTime); +} + +double MovingPoint::getVCoord(uint32_t d) const +{ + if (d < 0 && d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pVCoords[d]; +} + +void MovingPoint::getPointAtTime(double t, Point& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + out.m_pCoords[cDim] = getCoord(cDim, t); + } +} + +// +// IObject interface +// +MovingPoint* MovingPoint::clone() +{ + return new MovingPoint(*this); +} + +// +// ISerializable interface +// +uint32_t MovingPoint::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + 2 * m_dimension * sizeof(double)); +} + +void MovingPoint::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pCoords, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pVCoords, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void MovingPoint::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, m_pCoords, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pVCoords, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IEvolvingShape interface +// +void MovingPoint::getVMBR(Region& out) const +{ + out.makeDimension(m_dimension); + memcpy(out.m_pLow, m_pVCoords, m_dimension * sizeof(double)); + memcpy(out.m_pHigh, m_pVCoords, m_dimension * sizeof(double)); +} + +void MovingPoint::getMBRAtTime(double t, Region& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + out.m_pLow[cDim] = getCoord(cDim, t); + out.m_pHigh[cDim] = getCoord(cDim, t); + } +} + +void MovingPoint::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pCoords[cIndex] = std::numeric_limits<double>::max(); + m_pVCoords[cIndex] = -std::numeric_limits<double>::max(); + } + + m_startTime = std::numeric_limits<double>::max(); + m_endTime = -std::numeric_limits<double>::max(); +} + +void MovingPoint::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pCoords; + delete[] m_pVCoords; + m_pCoords = 0; m_pVCoords = 0; + + m_dimension = dimension; + m_pCoords = new double[m_dimension]; + m_pVCoords = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const MovingPoint& pt) +{ + uint32_t i; + + os << "Coords: "; + for (i = 0; i < pt.m_dimension; ++i) + { + os << pt.m_pCoords[i] << " "; + } + + os << "VCoords: "; + for (i = 0; i < pt.m_dimension; ++i) + { + os << pt.m_pVCoords[i] << " "; + } + + os << ", Start: " << pt.m_startTime << ", End: " << pt.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/MovingRegion.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/MovingRegion.cc new file mode 100644 index 000000000..8f54e4a37 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/MovingRegion.cc @@ -0,0 +1,1231 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +/* + * Does not support degenerate time intervals or shrinking regions. +*/ + + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +MovingRegion::MovingRegion() + : TimeRegion(), m_pVLow(0), m_pVHigh(0) +{ +} + +MovingRegion::MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + const IInterval& ivT, uint32_t dimension) +{ + initialize(pLow, pHigh, pVLow, pVHigh, ivT.getLowerBound(), ivT.getUpperBound(), dimension); +} + +MovingRegion::MovingRegion( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension) +{ + initialize(pLow, pHigh, pVLow, pVHigh, tStart, tEnd, dimension); +} + +MovingRegion::MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + const IInterval& ivT) +{ + if (low.m_dimension != high.m_dimension || low.m_dimension != vlow.m_dimension || vlow.m_dimension != vhigh.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize( + low.m_pCoords, high.m_pCoords, vlow.m_pCoords, vhigh.m_pCoords, + ivT.getLowerBound(), ivT.getUpperBound(), low.m_dimension); +} + +MovingRegion::MovingRegion( + const Point& low, const Point& high, + const Point& vlow, const Point& vhigh, + double tStart, double tEnd) +{ + if (low.m_dimension != high.m_dimension || low.m_dimension != vlow.m_dimension || vlow.m_dimension != vhigh.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize( + low.m_pCoords, high.m_pCoords, vlow.m_pCoords, vhigh.m_pCoords, + tStart, tEnd, low.m_dimension); +} + +MovingRegion::MovingRegion( + const Region& mbr, const Region& vbr, const IInterval& ivT) +{ + if (mbr.m_dimension != vbr.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize(mbr.m_pLow, mbr.m_pHigh, vbr.m_pLow, vbr.m_pHigh, ivT.getLowerBound(), ivT.getUpperBound(), mbr.m_dimension); +} + +MovingRegion::MovingRegion( + const Region& mbr, const Region& vbr, double tStart, double tEnd) +{ + if (mbr.m_dimension != vbr.m_dimension) + throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + initialize(mbr.m_pLow, mbr.m_pHigh, vbr.m_pLow, vbr.m_pHigh, tStart, tEnd, mbr.m_dimension); +} + +MovingRegion::MovingRegion(const MovingPoint& low, const MovingPoint& high) +{ + m_startTime = low.m_startTime; + m_endTime = high.m_endTime;; + m_dimension = low.m_dimension; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + if (m_endTime <= m_startTime) throw Tools::IllegalArgumentException("MovingRegion: Cannot support degenerate time intervals."); + + if (low.m_dimension != high.m_dimension) throw Tools::IllegalArgumentException("MovingRegion: arguments have different number of dimensions."); + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + + } + catch (...) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + throw; + } + + memcpy(m_pLow, low.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pHigh, high.m_pCoords, m_dimension * sizeof(double)); + memcpy(m_pVLow, low.m_pVCoords, m_dimension * sizeof(double)); + memcpy(m_pVHigh, high.m_pVCoords, m_dimension * sizeof(double)); +} + +MovingRegion::MovingRegion(const MovingRegion& r) +{ + m_startTime = r.m_startTime; + m_endTime = r.m_endTime; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + m_dimension = r.m_dimension; + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + throw; + } + + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + memcpy(m_pVLow, r.m_pVLow, m_dimension * sizeof(double)); + memcpy(m_pVHigh, r.m_pVHigh, m_dimension * sizeof(double)); +} + +void MovingRegion::initialize( + const double* pLow, const double* pHigh, + const double* pVLow, const double* pVHigh, + double tStart, double tEnd, uint32_t dimension) +{ + m_startTime = tStart; + m_endTime = tEnd; + m_dimension = dimension; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + if (m_endTime <= m_startTime) throw Tools::IllegalArgumentException("MovingRegion: Cannot support degenerate time intervals."); + +#ifndef NDEBUG + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (pLow[cDim] > pHigh[cDim]) throw Tools::IllegalArgumentException("MovingRegion: Low point has larger coordinates than High point."); + } +#endif + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + throw; + } + + // first store the point coordinates, than the point velocities. + memcpy(m_pLow, pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, pHigh, m_dimension * sizeof(double)); + memcpy(m_pVLow, pVLow, m_dimension * sizeof(double)); + memcpy(m_pVHigh, pVHigh, m_dimension * sizeof(double)); +} + +MovingRegion::~MovingRegion() +{ + delete[] m_pVLow; + delete[] m_pVHigh; +} + +MovingRegion& MovingRegion::operator=(const MovingRegion& r) +{ + if(this != &r) + { + makeDimension(r.m_dimension); + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + memcpy(m_pVLow, r.m_pVLow, m_dimension * sizeof(double)); + memcpy(m_pVHigh, r.m_pVHigh, m_dimension * sizeof(double)); + + m_startTime = r.m_startTime; + m_endTime = r.m_endTime; + + assert(m_startTime < m_endTime); + } + + return *this; +} + +bool MovingRegion::operator==(const MovingRegion& r) const +{ + if (m_startTime < r.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > r.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < r.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > r.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pLow[i] < r.m_pLow[i] - std::numeric_limits<double>::epsilon() || + m_pLow[i] > r.m_pLow[i] + std::numeric_limits<double>::epsilon() || + m_pHigh[i] < r.m_pHigh[i] - std::numeric_limits<double>::epsilon() || + m_pHigh[i] > r.m_pHigh[i] + std::numeric_limits<double>::epsilon() || + m_pVLow[i] < r.m_pVLow[i] - std::numeric_limits<double>::epsilon() || + m_pVLow[i] > r.m_pVLow[i] + std::numeric_limits<double>::epsilon() || + m_pVHigh[i] < r.m_pVHigh[i] - std::numeric_limits<double>::epsilon() || + m_pVHigh[i] > r.m_pVHigh[i] + std::numeric_limits<double>::epsilon()) + return false; + } + return true; +} + +bool MovingRegion::isShrinking() const +{ + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (m_pVHigh[cDim] < m_pVLow[cDim]) return true; + } + return false; +} + +// assumes that the region is not moving before and after start and end time. +double MovingRegion::getLow(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + if (t > m_endTime) return m_pLow[d] + m_pVLow[d] * (m_endTime - m_startTime); + else if (t < m_startTime) return m_pLow[d]; + else return m_pLow[d] + m_pVLow[d] * (t - m_startTime); +} + +// assumes that the region is not moving before and after start and end time. +double MovingRegion::getHigh(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + if (t > m_endTime) return m_pHigh[d] + m_pVHigh[d] * (m_endTime - m_startTime); + else if (t < m_startTime) return m_pHigh[d]; + else return m_pHigh[d] + m_pVHigh[d] * (t - m_startTime); +} + +// assuming that the region kept moving. +double MovingRegion::getExtrapolatedLow(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pLow[d] + m_pVLow[d] * (t - m_startTime); +} + +// assuming that the region kept moving. +double MovingRegion::getExtrapolatedHigh(uint32_t d, double t) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pHigh[d] + m_pVHigh[d] * (t - m_startTime); +} + +double MovingRegion::getVLow(uint32_t d) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pVLow[d]; +} + +double MovingRegion::getVHigh(uint32_t d) const +{ + if (d < 0 || d >= m_dimension) throw Tools::IndexOutOfBoundsException(d); + + return m_pVHigh[d]; +} + +bool MovingRegion::intersectsRegionInTime(const MovingRegion& r) const +{ + Tools::Interval ivOut; + return intersectsRegionInTime(r, ivOut); +} + +bool MovingRegion::intersectsRegionInTime(const MovingRegion& r, IInterval& ivOut) const +{ + return intersectsRegionInTime(r, r, ivOut); +} + +// if tmin, tmax are infinity then this will not work correctly (everything will always intersect). +// does not work for shrinking regions. +// does not work with degenerate time-intervals. +// +// WARNING: this will return true even if one region completely contains the other, since +// their areas do intersect in that case! +// +// there are various cases here: +// 1. one region contains the other. +// 2. one boundary of one region is always contained indide the other region, while the other +// boundary is not (so no boundaries will ever intersect). +// 3. either the upper or lower boundary of one region intersects a boundary of the other. +bool MovingRegion::intersectsRegionInTime(const IInterval& ivPeriod, const MovingRegion& r, IInterval& ivOut) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("intersectsRegionInTime: MovingRegions have different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(r.m_startTime < r.m_endTime); + assert(ivPeriod.getLowerBound() < ivPeriod.getUpperBound()); + assert(isShrinking() == false && r.isShrinking() == false); + + // this is needed, since we are assuming below that the two regions have some point of intersection + // inside itPeriod. + if (containsRegionInTime(ivPeriod, r) || r.containsRegionInTime(ivPeriod, *this)) + { + ivOut = ivPeriod; + return true; + } + + double tmin = std::max(m_startTime, r.m_startTime); + double tmax = std::min(m_endTime, r.m_endTime); + + // the regions do not intersect in time. + if (tmax <= tmin) return false; + + tmin = std::max(tmin, ivPeriod.getLowerBound()); + tmax = std::min(tmax, ivPeriod.getUpperBound()); + + // the regions intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return false; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + // I use projected low and high because they are faster and it does not matter. + // The are also necessary for calculating the intersection point with reference time instant 0.0. + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= r.m_startTime && tmax <= r.m_endTime); + + // completely above or bellow in i-th dimension + if ( + (r.getExtrapolatedLow(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) && + r.getExtrapolatedLow(cDim, tmax) >= getExtrapolatedHigh(cDim, tmax)) || + (r.getExtrapolatedHigh(cDim, tmin) < getExtrapolatedLow(cDim, tmin) && + r.getExtrapolatedHigh(cDim, tmax) <= getExtrapolatedLow(cDim, tmax))) + return false; + + // otherwise they intersect inside this interval for sure. Care needs to be taken since + // intersection does not necessarily mean that two line segments intersect. It could be + // that one line segment is completely above/below another, in which case there is no intersection + // point inside tmin, tmax, even though the two region areas do intersect. + + if (r.getExtrapolatedLow(cDim, tmin) > getExtrapolatedHigh(cDim, tmin)) // r above *this at tmin + { + tmin = (getExtrapolatedHigh(cDim, 0.0) - r.getExtrapolatedLow(cDim, 0.0)) / (r.getVLow(cDim) - getVHigh(cDim)); + } + else if (r.getExtrapolatedHigh(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) // r below *this at tmin + { + tmin = (getExtrapolatedLow(cDim, 0.0) - r.getExtrapolatedHigh(cDim, 0.0)) / (r.getVHigh(cDim) - getVLow(cDim)); + } + // else they do not intersect and the boundary might be completely contained in this region. + + if (r.getExtrapolatedLow(cDim, tmax) > getExtrapolatedHigh(cDim, tmax)) // r above *this at tmax + { + tmax = (getExtrapolatedHigh(cDim, 0.0) - r.getExtrapolatedLow(cDim, 0.0)) / (r.getVLow(cDim) - getVHigh(cDim)); + } + else if (r.getExtrapolatedHigh(cDim, tmax) < getExtrapolatedLow(cDim, tmax)) // r below *this at tmax + { + tmax = (getExtrapolatedLow(cDim, 0.0) - r.getExtrapolatedHigh(cDim, 0.0)) / (r.getVHigh(cDim) - getVLow(cDim)); + } + // else they do not intersect and the boundary might be completely contained in this region. + + assert(tmin <= tmax); + } + + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= r.m_startTime && tmax <= r.m_endTime); + + ivOut.setBounds(tmin, tmax); + + return true; +} + +bool MovingRegion::containsRegionInTime(const MovingRegion& r) const +{ + return containsRegionInTime(r, r); +} + +// does not work for shrinking regions. +// works fine for infinite bounds (both tmin and tmax). +// does not work with degenerate time-intervals. +// +// finds if during the intersecting time-interval of r and ivPeriod, r is completely contained in *this. +bool MovingRegion::containsRegionInTime(const IInterval& ivPeriod, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("containsRegionInTime: MovingRegions have different number of dimensions."); + + assert(isShrinking() == false && r.isShrinking() == false); + + double tmin = std::max(ivPeriod.getLowerBound(), r.m_startTime); + double tmax = std::min(ivPeriod.getUpperBound(), r.m_endTime); + + // it should be contained in time. + // it does not make sense if this region is not defined for any part ot [tmin, tmax]. + if (tmax <= tmin || tmin < m_startTime || tmax > m_endTime) return false; + + double intersectionTime; + + // no need to take projected coordinates here, since tmin and tmax are always contained in + // the regions intersecting time-intervals. + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= r.m_startTime && tmax <= r.m_endTime); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + // it should be contained at start time. + if (r.getExtrapolatedHigh(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) || + r.getExtrapolatedLow(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) return false; + + // this will take care of infinite bounds. + if (r.m_pVHigh[cDim] != m_pVHigh[cDim]) + { + intersectionTime = (getExtrapolatedHigh(cDim, 0.0) - r.getExtrapolatedHigh(cDim, 0.0)) / (r.m_pVHigh[cDim] - m_pVHigh[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && r.m_pVHigh[cDim] > m_pVHigh[cDim]) return false; + } + + if (r.m_pVLow[cDim] != m_pVLow[cDim]) + { + intersectionTime = (getExtrapolatedLow(cDim, 0.0) - r.getExtrapolatedLow(cDim, 0.0)) / (r.m_pVLow[cDim] - m_pVLow[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && r.m_pVLow[cDim] < m_pVLow[cDim]) return false; + } + } + + return true; +} + +bool MovingRegion::containsRegionAfterTime(double t, const MovingRegion& r) const +{ + Tools::Interval ivT(t, r.m_endTime); + return containsRegionInTime(ivT, r); +} + +// Returns the area swept by the rectangle in time, in d-dimensional space (without +// including the temporal dimension, that is). +// This is what Saltenis calls Margin (which is different than what Beckmann proposes, +// where he computes only the wireframe -- instead of the surface/volume/etc. -- of the MBR in any dimension). +double MovingRegion::getProjectedSurfaceAreaInTime() const +{ + return getProjectedSurfaceAreaInTime(*this); +} + +double MovingRegion::getProjectedSurfaceAreaInTime(const IInterval& ivI) const +{ + double tmin = std::max(ivI.getLowerBound(), m_startTime); + double tmax = std::min(ivI.getUpperBound(), m_endTime); + + assert(tmin > -std::numeric_limits<double>::max()); + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin <= tmax); + + if (tmin >= tmax - std::numeric_limits<double>::epsilon() && + tmin <= tmax + std::numeric_limits<double>::epsilon()) + return 0.0; + + double dx1, dx2, dx3; + double dv1, dv2, dv3; + double H = tmax - tmin; + + if (m_dimension == 3) + { + dx3 = getExtrapolatedHigh(2, tmin) - getExtrapolatedLow(2, tmin); + dv3 = getVHigh(2) - getVLow(2); + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return + H * (dx1 + dx2 + dx3 + dx1*dx2 + dx1*dx3 + dx2*dx3) + + H*H * (dv1 + dv2 + dv3 + dx1*dv2 + dv1*dx2 + dx1*dv3 + + dv1*dx3 + dx2*dv3 + dv2*dx3) / 2.0 + + H*H*H * (dv1*dv2 + dv1*dv3 + dv2*dv3) / 3.0; + } + else if (m_dimension == 2) + { + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return H * (dx1 + dx2) + H * H * (dv1 + dv2) / 2.0; + } + else if (m_dimension == 1) + { + // marioh: why not use the increase of the length of the interval here? + return 0.0; + } + else + { + throw Tools::IllegalStateException("getProjectedSurfaceAreaInTime: unsupported dimensionality."); + } +} + +double MovingRegion::getCenterDistanceInTime(const MovingRegion& r) const +{ + + return getCenterDistanceInTime(r, r); +} + +double MovingRegion::getCenterDistanceInTime(const IInterval& ivI, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("getCenterDistanceInTime: MovingRegions have different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(r.m_startTime < r.m_endTime); + assert(ivI.getLowerBound() < ivI.getUpperBound()); + + double tmin = std::max(m_startTime, r.m_startTime); + double tmax = std::min(m_endTime, r.m_endTime); + + // the regions do not intersect in time. + if (tmax <= tmin) return 0.0; + + tmin = std::max(tmin, ivI.getLowerBound()); + tmax = std::min(tmax, ivI.getUpperBound()); + + // the regions intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return 0.0; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + if (tmin >= tmax - std::numeric_limits<double>::epsilon() && + tmin <= tmax + std::numeric_limits<double>::epsilon()) + return 0.0; + + double H = tmax - tmin; + + double* dx = new double[m_dimension]; + double* dv = new double[m_dimension]; + double a = 0.0, b = 0.0, c = 0.0, f = 0.0, l = 0.0, m = 0.0, n = 0.0; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + dx[cDim] = + (r.getExtrapolatedLow(cDim, tmin) + r.getExtrapolatedHigh(cDim, tmin)) / 2.0 - + (getExtrapolatedLow(cDim, tmin) + getExtrapolatedHigh(cDim, tmin)) / 2.0; + dv[cDim] = + (r.getVLow(cDim) + r.getVHigh(cDim)) / 2.0 - + (getVLow(cDim) + getVHigh(cDim)) / 2.0; + } + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + a += dv[cDim] * dv[cDim]; + b += 2.0 * dx[cDim] * dv[cDim]; + c += dx[cDim] * dx[cDim]; + } + + if (a == 0.0 && c == 0.0) return 0.0; + if (a == 0.0) return H * std::sqrt(c); + if (c == 0.0) return H * H * std::sqrt(a) / 2.0; + + f = std::sqrt(a * H * H + b * H + c); + l = 2.0 * a * H + b; + m = 4.0 * a * c - b * b; + n = 2.0 * std::sqrt(a); + + delete[] dx; + delete[] dv; + + return (l * f + log(l / n + f) * m / n - b * std::sqrt(c) - std::log(b / n + std::sqrt(c)) * m / n) / (4.0 * a); +} + +// does not work with degenerate time-intervals. +bool MovingRegion::intersectsRegionAtTime(double t, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("intersectsRegionAtTime: MovingRegions have different number of dimensions."); + + // do they contain the time instant? + if (! (m_startTime <= t && t < m_endTime && r.m_startTime <= t && t < r.m_endTime)) return false; + + // do they intersect at that time instant? + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (getExtrapolatedLow(i, t) > r.getExtrapolatedHigh(i, t) || getExtrapolatedHigh(i, t) < r.getExtrapolatedLow(i, t)) return false; + } + return true; +} + +// does not work with degenerate time-intervals. +bool MovingRegion::containsRegionAtTime(double t, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("containsRegionAtTime: MovingRegions have different number of dimensions."); + + // do they contain the time instant? + if (! (m_startTime <= t && t < m_endTime && r.m_startTime <= t && t < r.m_endTime)) return false; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (getExtrapolatedLow(cDim, t) > r.getExtrapolatedLow(cDim, t) || getExtrapolatedHigh(cDim, t) < getExtrapolatedHigh(cDim, t)) return false; + } + return true; +} + +bool MovingRegion::intersectsPointInTime(const MovingPoint& p) const +{ + Tools::Interval ivOut; + return intersectsPointInTime(p, ivOut); +} + +bool MovingRegion::intersectsPointInTime(const MovingPoint& p, IInterval& ivOut) const +{ + return intersectsPointInTime(p, p, ivOut); +} + +// if tmin, tmax are infinity then this will not work correctly (everything will always intersect). +// does not work for shrinking regions. +// does not work with degenerate time-intervals. +// FIXME: don't know what happens if tmin is negative infinity. +// +// WARNING: This will return true even if the region completely contains the point, since +// in that case the point trajectory intersects the region area! +bool MovingRegion::intersectsPointInTime(const IInterval& ivPeriod, const MovingPoint& p, IInterval& ivOut) const +{ + if (m_dimension != p.m_dimension) throw Tools::IllegalArgumentException("intersectsPointInTime: MovingPoint has different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(p.m_startTime < p.m_endTime); + assert(ivPeriod.getLowerBound() < ivPeriod.getUpperBound()); + assert(isShrinking() == false); + + if (containsPointInTime(ivPeriod, p)) + { + ivOut = ivPeriod; + return true; + } + + double tmin = std::max(m_startTime, p.m_startTime); + double tmax = std::min(m_endTime, p.m_endTime); + + // the shapes do not intersect in time. + if (tmax <= tmin) return false; + + tmin = std::max(tmin, ivPeriod.getLowerBound()); + tmax = std::min(tmax, ivPeriod.getUpperBound()); + + // the shapes intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return false; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= p.m_startTime && tmax <= p.m_endTime); + + // completely above or bellow in i-th dimension + if ((p.getProjectedCoord(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) && + p.getProjectedCoord(cDim, tmax) >= getExtrapolatedHigh(cDim, tmax)) || + (p.getProjectedCoord(cDim, tmin) < getExtrapolatedLow(cDim, tmin) && + p.getProjectedCoord(cDim, tmax) <= getExtrapolatedLow(cDim, tmax))) + return false; + + // otherwise they intersect inside this interval for sure, since we know that the point is not contained, + // so there is no need to check for 0 divisors, negative values, etc... + + // adjust tmin + if (p.getProjectedCoord(cDim, tmin) > getExtrapolatedHigh(cDim, tmin)) // p above *this at tmin + { + tmin = (getExtrapolatedHigh(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVHigh(cDim)); + } + else if (p.getProjectedCoord(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) // p below *this at tmin + { + tmin = (getExtrapolatedLow(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVLow(cDim)); + } + + // adjust tmax + if (p.getProjectedCoord(cDim, tmax) > getExtrapolatedHigh(cDim, tmax)) // p above *this at tmax + { + tmax = (getExtrapolatedHigh(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVHigh(cDim)); + } + else if (p.getProjectedCoord(cDim, tmax) < getExtrapolatedLow(cDim, tmax)) // p below *this at tmax + { + tmax = (getExtrapolatedLow(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.getVCoord(cDim) - getVLow(cDim)); + } + + if (tmin > tmax) return false; + } + + ivOut.setBounds(tmin, tmax); + + return true; +} + +bool MovingRegion::containsPointInTime(const MovingPoint& p) const +{ + return containsPointInTime(p, p); +} + +// does not work for shrinking regions. +// works fine for infinite bounds (both tmin and tmax). +// does not work with degenerate time-intervals. +// +// finds if during the intersecting time-interval of p and ivPeriod, p is completely contained in *this. +bool MovingRegion::containsPointInTime(const IInterval& ivPeriod, const MovingPoint& p) const +{ + if (m_dimension != p.m_dimension) throw Tools::IllegalArgumentException("containsPointInTime: MovingPoint has different number of dimensions."); + + assert(isShrinking() == false); + + double tmin = std::max(ivPeriod.getLowerBound(), p.m_startTime); + double tmax = std::min(ivPeriod.getUpperBound(), p.m_endTime); + + // it should be contained in time. + if (tmax <= tmin || tmin < m_startTime || tmax > m_endTime) return false; + + double intersectionTime; + + assert( + tmin >= ivPeriod.getLowerBound() && tmax <= ivPeriod.getUpperBound() && + tmin >= m_startTime && tmax <= m_endTime && + tmin >= p.m_startTime && tmax <= p.m_endTime); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + // it should be contained at start time. + if (p.getProjectedCoord(cDim, tmin) > getExtrapolatedHigh(cDim, tmin) || + p.getProjectedCoord(cDim, tmin) < getExtrapolatedLow(cDim, tmin)) return false; + + if (p.m_pVCoords[cDim] != m_pVHigh[cDim]) + { + intersectionTime = (getExtrapolatedHigh(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.m_pVCoords[cDim] - m_pVHigh[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && p.m_pVCoords[cDim] > m_pVHigh[cDim]) return false; + } + + if (p.m_pVCoords[cDim] != m_pVLow[cDim]) + { + intersectionTime = (getExtrapolatedLow(cDim, 0.0) - p.getProjectedCoord(cDim, 0.0)) / (p.m_pVCoords[cDim] - m_pVLow[cDim]); + // if they intersect during this time-interval, then it is not contained. + if (tmin < intersectionTime && intersectionTime < tmax) return false; + if (tmin == intersectionTime && p.m_pVCoords[cDim] < m_pVLow[cDim]) return false; + } + } + + return true; +} + +void MovingRegion::combineRegionInTime(const MovingRegion& r) +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("combineRegionInTime: MovingRegions have different number of dimensions."); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(getExtrapolatedLow(cDim, m_startTime), r.getExtrapolatedLow(cDim, m_startTime)); + m_pHigh[cDim] = std::max(getExtrapolatedHigh(cDim, m_startTime), r.getExtrapolatedHigh(cDim, m_startTime)); + m_pVLow[cDim] = std::min(m_pVLow[cDim], r.m_pVLow[cDim]); + m_pVHigh[cDim] = std::max(m_pVHigh[cDim], r.m_pVHigh[cDim]); + } + + // m_startTime should be modified at the end, since it affects the + // calculation of extrapolated coordinates. + m_startTime = std::min(m_startTime, r.m_startTime); + m_endTime = std::max(m_endTime, r.m_endTime); +} + +void MovingRegion::getCombinedRegionInTime(MovingRegion& out, const MovingRegion& in) const +{ + if (m_dimension != in.m_dimension) throw Tools::IllegalArgumentException("getCombinedProjectedRegionInTime: MovingRegions have different number of dimensions."); + + out = *this; + out.combineRegionInTime(in); +} + +void MovingRegion::combineRegionAfterTime(double t, const MovingRegion& r) +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("combineRegionInTime: MovingRegions have different number of dimensions."); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(getExtrapolatedLow(cDim, t), r.getExtrapolatedLow(cDim, t)); + m_pHigh[cDim] = std::max(getExtrapolatedHigh(cDim, t), r.getExtrapolatedHigh(cDim, t)); + m_pVLow[cDim] = std::min(m_pVLow[cDim], r.m_pVLow[cDim]); + m_pVHigh[cDim] = std::max(m_pVHigh[cDim], r.m_pVHigh[cDim]); + } + + // m_startTime should be modified at the end, since it affects the + // calculation of extrapolated coordinates. + m_startTime = t; + m_endTime = std::max(m_endTime, r.m_endTime); + if (t >= m_endTime) m_endTime = std::numeric_limits<double>::max(); +} + +void MovingRegion::getCombinedRegionAfterTime(double t, MovingRegion& out, const MovingRegion& in) const +{ + if (m_dimension != in.m_dimension) throw Tools::IllegalArgumentException("getCombinedProjectedRegionInTime: MovingRegions have different number of dimensions."); + + out = *this; + out.combineRegionAfterTime(t, in); +} + +double MovingRegion::getIntersectingAreaInTime(const MovingRegion& r) const +{ + return getIntersectingAreaInTime(r, r); +} + +double MovingRegion::getIntersectingAreaInTime(const IInterval& ivI, const MovingRegion& r) const +{ + if (m_dimension != r.m_dimension) throw Tools::IllegalArgumentException("getIntersectingAreaInTime: MovingRegions have different number of dimensions."); + + assert(m_startTime < m_endTime); + assert(r.m_startTime < r.m_endTime); + assert(ivI.getLowerBound() < ivI.getUpperBound()); + assert(isShrinking() == false && r.isShrinking() == false); + + double tmin = std::max(m_startTime, r.m_startTime); + double tmax = std::min(m_endTime, r.m_endTime); + + // the regions do not intersect in time. + if (tmax <= tmin) return 0.0; + + tmin = std::max(tmin, ivI.getLowerBound()); + tmax = std::min(tmax, ivI.getUpperBound()); + + // the regions intersecting interval does not intersect with the given time period. + if (tmax <= tmin) return 0.0; + + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin > -std::numeric_limits<double>::max()); + + Tools::Interval ivIn(tmin, tmax); + Tools::Interval ivOut(ivIn); + + if (! intersectsRegionInTime(ivIn, r, ivOut)) return 0.0; + + ivIn = ivOut; + tmin = ivIn.getLowerBound(); + tmax = ivIn.getUpperBound(); + assert(tmin <= tmax); + + assert(tmin >= ivI.getLowerBound() && tmax <= ivI.getUpperBound()); + + if (containsRegionInTime(ivIn, r)) + { + return r.getAreaInTime(ivIn); + } + else if (r.containsRegionInTime(ivIn, *this)) + { + return getAreaInTime(ivIn); + } + + MovingRegion x = *this; + CrossPoint c; + std::priority_queue<CrossPoint, std::vector<CrossPoint>, CrossPoint::ascending> pq; + + // find points of intersection in all dimensions. + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (getLow(i, tmin) > r.getLow(i, tmin)) + { + x.m_pLow[i] = m_pLow[i]; + x.m_pVLow[i] = m_pVLow[i]; + + if (getLow(i, tmax) < r.getLow(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 0; + c.m_t = (getExtrapolatedLow(i, 0.0) - r.getExtrapolatedLow(i, 0.0)) / (r.getVLow(i) - getVLow(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = &r; + pq.push(c); + } + } + else + { + x.m_pLow[i] = r.m_pLow[i]; + x.m_pVLow[i] = r.m_pVLow[i]; + + if (r.getLow(i, tmax) < getLow(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 0; + c.m_t = (getExtrapolatedLow(i, 0.0) - r.getExtrapolatedLow(i, 0.0)) / (r.getVLow(i) - getVLow(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = this; + pq.push(c); + } + } + + if (getHigh(i, tmin) < r.getHigh(i, tmin)) + { + x.m_pHigh[i] = m_pHigh[i]; + x.m_pVHigh[i] = m_pVHigh[i]; + + if (getHigh(i, tmax) > r.getHigh(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 1; + c.m_t = (getExtrapolatedHigh(i, 0.0) - r.getExtrapolatedHigh(i, 0.0)) / (r.getVHigh(i) - getVHigh(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = &r; + pq.push(c); + } + } + else + { + x.m_pHigh[i] = r.m_pHigh[i]; + x.m_pVHigh[i] = r.m_pVHigh[i]; + + if (r.getHigh(i, tmax) > getHigh(i, tmax)) + { + c.m_dimension = i; + c.m_boundary = 1; + c.m_t = (getExtrapolatedHigh(i, 0.0) - r.getExtrapolatedHigh(i, 0.0)) / (r.getVHigh(i) - getVHigh(i)); + assert(c.m_t >= tmin && c.m_t <= tmax); + c.m_to = this; + pq.push(c); + } + } + } + + // add up the total area of the intersecting pieces. + double area = 0.0; +#ifndef NDEBUG + double _t = -std::numeric_limits<double>::max(); +#endif + + while (! pq.empty()) + { + c = pq.top(); pq.pop(); +#ifndef NDEBUG + assert(_t <= c.m_t); + _t = c.m_t; +#endif + + // needed in case two consecutive points have the same intersection time. + if (c.m_t > tmin) area += x.getAreaInTime(Tools::Interval(tmin, c.m_t)); + + if (c.m_boundary == 0) + { + x.m_pLow[c.m_dimension] = c.m_to->m_pLow[c.m_dimension]; + x.m_pVLow[c.m_dimension] = c.m_to->m_pVLow[c.m_dimension]; + } + else + { + x.m_pHigh[c.m_dimension] = c.m_to->m_pHigh[c.m_dimension]; + x.m_pVHigh[c.m_dimension] = c.m_to->m_pVHigh[c.m_dimension]; + } + + tmin = c.m_t; + } + + // ... and the last piece + if (tmax > tmin) area += x.getAreaInTime(Tools::Interval(tmin, tmax)); + + return area; +} + +// +// IObject interface +// +MovingRegion* MovingRegion::clone() +{ + return new MovingRegion(*this); +} + +// +// ISerializable interface +// +uint32_t MovingRegion::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + 4 * m_dimension * sizeof(double)); +} + +void MovingRegion::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pHigh, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pVLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pVHigh, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void MovingRegion::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, m_pLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pHigh, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pVLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pVHigh, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IEvolvingShape interface +// +void MovingRegion::getVMBR(Region& out) const +{ + out.makeDimension(m_dimension); + memcpy(out.m_pLow, m_pVLow, m_dimension * sizeof(double)); + memcpy(out.m_pHigh, m_pVHigh, m_dimension * sizeof(double)); +} + +void MovingRegion::getMBRAtTime(double t, Region& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + out.m_pLow[cDim] = getLow(cDim, t); + out.m_pHigh[cDim] = getHigh(cDim, t); + } +} + +// +// ITimeShape interface +// +double MovingRegion::getAreaInTime() const +{ + return getAreaInTime(*this); +} + +// this computes the area/volume/etc. swept by the Region in time. +double MovingRegion::getAreaInTime(const IInterval& ivI) const +{ + double tmin = std::max(ivI.getLowerBound(), m_startTime); + double tmax = std::min(ivI.getUpperBound(), m_endTime); + + assert(tmin > -std::numeric_limits<double>::max()); + assert(tmax < std::numeric_limits<double>::max()); + assert(tmin <= tmax); + + if (tmin >= tmax - std::numeric_limits<double>::epsilon() && + tmin <= tmax + std::numeric_limits<double>::epsilon()) + return 0.0; + + double dx1, dx2, dx3; + double dv1, dv2, dv3; + double H = tmax - tmin; + + if (m_dimension == 3) + { + dx3 = getExtrapolatedHigh(2, tmin) - getExtrapolatedLow(2, tmin); + dv3 = getVHigh(2) - getVLow(2); + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return + H * dx1 * dx2 * dx3 + H * H * (dx1 * dx2 * dv3 + (dx1 * dv2 + dv1 * dx2) * dx3) / 2.0 + + H * H * H * ((dx1 * dv2 + dv1 * dx2) * dv3 + dv1 * dv2 * dx3) / 3.0 + H * H * H * H * dv1 * dv2 * dv3 / 4.0; + } + else if (m_dimension == 2) + { + dx2 = getExtrapolatedHigh(1, tmin) - getExtrapolatedLow(1, tmin); + dv2 = getVHigh(1) - getVLow(1); + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return H * dx1 * dx2 + H * H * (dx1 * dv2 + dv1 * dx2) / 2.0 + H * H * H * dv1 * dv2 / 3.0; + } + else if (m_dimension == 1) + { + dx1 = getExtrapolatedHigh(0, tmin) - getExtrapolatedLow(0, tmin); + dv1 = getVHigh(0) - getVLow(0); + return H * dx1 + H * H * dv1 / 2.0; + } + else + { + throw Tools::NotSupportedException("getAreaInTime: unsupported dimensionality."); + } +} + +double MovingRegion::getIntersectingAreaInTime(const ITimeShape& r) const +{ + return getIntersectingAreaInTime(r, r); +} + +double MovingRegion::getIntersectingAreaInTime(const IInterval& ivI, const ITimeShape& in) const +{ + const MovingRegion* pr = dynamic_cast<const MovingRegion*>(&in); + if (pr != 0) return getIntersectingAreaInTime(*pr); + + throw Tools::IllegalStateException("getIntersectingAreaInTime: Not implemented yet!"); +} + +void MovingRegion::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pLow[cIndex] = std::numeric_limits<double>::max(); + m_pHigh[cIndex] = -std::numeric_limits<double>::max(); + m_pVLow[cIndex] = std::numeric_limits<double>::max(); + m_pVHigh[cIndex] = -std::numeric_limits<double>::max(); + } + + m_startTime = -std::numeric_limits<double>::max(); + m_endTime = std::numeric_limits<double>::max(); +} + +void MovingRegion::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pLow; + delete[] m_pHigh; + delete[] m_pVLow; + delete[] m_pVHigh; + m_pLow = 0; m_pHigh = 0; + m_pVLow = 0; m_pVHigh = 0; + + m_dimension = dimension; + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + m_pVLow = new double[m_dimension]; + m_pVHigh = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const MovingRegion& r) +{ + uint32_t i; + + os << "Low: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pLow[i] << " "; + } + + os << ", High: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pHigh[i] << " "; + } + + os << "VLow: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pVLow[i] << " "; + } + + os << ", VHigh: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pVHigh[i] << " "; + } + + os << ", Start: " << r.m_startTime << ", End: " << r.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Point.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Point.cc new file mode 100644 index 000000000..8c36c1123 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Point.cc @@ -0,0 +1,262 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +Point::Point() + : m_dimension(0), m_pCoords(0) +{ +} + +Point::Point(const double* pCoords, uint32_t dimension) + : m_dimension(dimension) +{ + // no need to initialize m_pCoords to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pCoords = new double[m_dimension]; + memcpy(m_pCoords, pCoords, m_dimension * sizeof(double)); +} + +Point::Point(const Point& p) + : m_dimension(p.m_dimension) +{ + // no need to initialize m_pCoords to 0 since if a bad_alloc is raised the destructor will not be called. + + m_pCoords = new double[m_dimension]; + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); +} + +Point::~Point() +{ + delete[] m_pCoords; +} + +Point& Point::operator=(const Point& p) +{ + if (this != &p) + { + makeDimension(p.m_dimension); + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + } + + return *this; +} + +bool Point::operator==(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Point::operator==: Points have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pCoords[i] < p.m_pCoords[i] - std::numeric_limits<double>::epsilon() || + m_pCoords[i] > p.m_pCoords[i] + std::numeric_limits<double>::epsilon()) return false; + } + + return true; +} + +// +// IObject interface +// +Point* Point::clone() +{ + return new Point(*this); +} + +// +// ISerializable interface +// +uint32_t Point::getByteArraySize() +{ + return (sizeof(uint32_t) + m_dimension * sizeof(double)); +} + +void Point::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + makeDimension(dimension); + memcpy(m_pCoords, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void Point::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, m_pCoords, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IShape interface +// +bool Point::intersectsShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->containsPoint(*this); + } + + throw Tools::IllegalStateException( + "Point::intersectsShape: Not implemented yet!" + ); +} + +bool Point::containsShape(const IShape& s) const +{ + return false; +} + +bool Point::touchesShape(const IShape& s) const +{ + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) + { + if (*this == *ppt) return true; + return false; + } + + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->touchesPoint(*this); + } + + throw Tools::IllegalStateException( + "Point::touchesShape: Not implemented yet!" + ); +} + +void Point::getCenter(Point& out) const +{ + out = *this; +} + +uint32_t Point::getDimension() const +{ + return m_dimension; +} + +void Point::getMBR(Region& out) const +{ + out = Region(m_pCoords, m_pCoords, m_dimension); +} + +double Point::getArea() const +{ + return 0.0; +} + +double Point::getMinimumDistance(const IShape& s) const +{ + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) + { + return getMinimumDistance(*ppt); + } + + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) + { + return pr->getMinimumDistance(*this); + } + + throw Tools::IllegalStateException( + "Point::getMinimumDistance: Not implemented yet!" + ); +} + +double Point::getMinimumDistance(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Point::getMinimumDistance: Shapes have different number of dimensions." + ); + + double ret = 0.0; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + ret += std::pow(m_pCoords[cDim] - p.m_pCoords[cDim], 2.0); + } + + return std::sqrt(ret); +} + +double Point::getCoordinate(uint32_t index) const +{ + if (index < 0 || index >= m_dimension) + throw Tools::IndexOutOfBoundsException(index); + + return m_pCoords[index]; +} + +void Point::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pCoords[cIndex] = std::numeric_limits<double>::max(); + } +} + +void Point::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pCoords; + + // remember that this is not a constructor. The object will be destructed normally if + // something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state. + m_pCoords = 0; + + m_dimension = dimension; + m_pCoords = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const Point& pt) +{ + for (uint32_t cDim = 0; cDim < pt.m_dimension; ++cDim) + { + os << pt.m_pCoords[cDim] << " "; + } + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Region.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Region.cc new file mode 100644 index 000000000..8db029831 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/Region.cc @@ -0,0 +1,554 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../../include/SpatialIndex.h" + +#include <cstring> +#include <cmath> +#include <limits> + +using namespace SpatialIndex; + +Region::Region() + : m_dimension(0), m_pLow(0), m_pHigh(0) +{ +} + +Region::Region(const double* pLow, const double* pHigh, uint32_t dimension) +{ + initialize(pLow, pHigh, dimension); +} + +Region::Region(const Point& low, const Point& high) +{ + if (low.m_dimension != high.m_dimension) + throw Tools::IllegalArgumentException( + "Region::Region: arguments have different number of dimensions." + ); + + initialize(low.m_pCoords, high.m_pCoords, low.m_dimension); +} + +Region::Region(const Region& r) +{ + initialize(r.m_pLow, r.m_pHigh, r.m_dimension); +} + +void Region::initialize(const double* pLow, const double* pHigh, uint32_t dimension) +{ + m_pLow = 0; + m_dimension = dimension; + +#ifndef NDEBUG + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if ((pLow[cDim] > pHigh[cDim])) + { + // check for infinitive region + if (!(pLow[cDim] == std::numeric_limits<double>::max() || + pHigh[cDim] == -std::numeric_limits<double>::max() )) + throw Tools::IllegalArgumentException( + "Region::initialize: Low point has larger coordinates than High point." + " Neither point is infinity." + ); + } + } +#endif + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + throw; + } + + memcpy(m_pLow, pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, pHigh, m_dimension * sizeof(double)); +} + +Region::~Region() +{ + delete[] m_pLow; + delete[] m_pHigh; +} + +Region& Region::operator=(const Region& r) +{ + if(this != &r) + { + makeDimension(r.m_dimension); + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + } + + return *this; +} + +bool Region::operator==(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::operator==: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pLow[i] < r.m_pLow[i] - std::numeric_limits<double>::epsilon() || + m_pLow[i] > r.m_pLow[i] + std::numeric_limits<double>::epsilon() || + m_pHigh[i] < r.m_pHigh[i] - std::numeric_limits<double>::epsilon() || + m_pHigh[i] > r.m_pHigh[i] + std::numeric_limits<double>::epsilon()) + return false; + } + return true; +} + +// +// IObject interface +// +Region* Region::clone() +{ + return new Region(*this); +} + +// +// ISerializable interface +// +uint32_t Region::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * m_dimension * sizeof(double)); +} + +void Region::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + makeDimension(dimension); + memcpy(m_pLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pHigh, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void Region::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, m_pLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pHigh, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// IShape interface +// +bool Region::intersectsShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return intersectsRegion(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return containsPoint(*ppt); + + throw Tools::IllegalStateException( + "Region::intersectsShape: Not implemented yet!" + ); +} + +bool Region::containsShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return containsRegion(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return containsPoint(*ppt); + + throw Tools::IllegalStateException( + "Region::containsShape: Not implemented yet!" + ); +} + +bool Region::touchesShape(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return touchesRegion(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return touchesPoint(*ppt); + + throw Tools::IllegalStateException( + "Region::touchesShape: Not implemented yet!" + ); +} + +void Region::getCenter(Point& out) const +{ + out.makeDimension(m_dimension); + for (uint32_t i = 0; i < m_dimension; ++i) + { + out.m_pCoords[i] = (m_pLow[i] + m_pHigh[i]) / 2.0; + } +} + +uint32_t Region::getDimension() const +{ + return m_dimension; +} + +void Region::getMBR(Region& out) const +{ + out = *this; +} + +double Region::getArea() const +{ + double area = 1.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + area *= m_pHigh[i] - m_pLow[i]; + } + + return area; +} + +double Region::getMinimumDistance(const IShape& s) const +{ + const Region* pr = dynamic_cast<const Region*>(&s); + if (pr != 0) return getMinimumDistance(*pr); + + const Point* ppt = dynamic_cast<const Point*>(&s); + if (ppt != 0) return getMinimumDistance(*ppt); + + throw Tools::IllegalStateException( + "Region::getMinimumDistance: Not implemented yet!" + ); +} + +bool Region::intersectsRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::intersectsRegion: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (m_pLow[i] > r.m_pHigh[i] || m_pHigh[i] < r.m_pLow[i]) return false; + } + return true; +} + +bool Region::containsRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::containsRegion: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (m_pLow[i] > r.m_pLow[i] || m_pHigh[i] < r.m_pHigh[i]) return false; + } + return true; +} + +bool Region::touchesRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::touchesRegion: Regions have different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + (m_pLow[i] >= r.m_pLow[i] + std::numeric_limits<double>::epsilon() && + m_pLow[i] <= r.m_pLow[i] - std::numeric_limits<double>::epsilon()) || + (m_pHigh[i] >= r.m_pHigh[i] + std::numeric_limits<double>::epsilon() && + m_pHigh[i] <= r.m_pHigh[i] - std::numeric_limits<double>::epsilon())) + return false; + } + return true; +} + +double Region::getMinimumDistance(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getMinimumDistance: Regions have different number of dimensions." + ); + + double ret = 0.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + double x = 0.0; + + if (r.m_pHigh[i] < m_pLow[i]) + { + x = std::abs(r.m_pHigh[i] - m_pLow[i]); + } + else if (m_pHigh[i] < r.m_pLow[i]) + { + x = std::abs(r.m_pLow[i] - m_pHigh[i]); + } + + ret += x * x; + } + + return std::sqrt(ret); +} + +bool Region::containsPoint(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::containsPoint: Point has different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (m_pLow[i] > p.getCoordinate(i) || m_pHigh[i] < p.getCoordinate(i)) return false; + } + return true; +} + +bool Region::touchesPoint(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::touchesPoint: Point has different number of dimensions." + ); + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + (m_pLow[i] >= p.getCoordinate(i) - std::numeric_limits<double>::epsilon() && + m_pLow[i] <= p.getCoordinate(i) + std::numeric_limits<double>::epsilon()) || + (m_pHigh[i] >= p.getCoordinate(i) - std::numeric_limits<double>::epsilon() && + m_pHigh[i] <= p.getCoordinate(i) + std::numeric_limits<double>::epsilon())) + return true; + } + return false; +} + +double Region::getMinimumDistance(const Point& p) const +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getMinimumDistance: Point has different number of dimensions." + ); + + double ret = 0.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if (p.getCoordinate(i) < m_pLow[i]) + { + ret += std::pow(m_pLow[i] - p.getCoordinate(i), 2.0); + } + else if (p.getCoordinate(i) > m_pHigh[i]) + { + ret += std::pow(p.getCoordinate(i) - m_pHigh[i], 2.0); + } + } + + return std::sqrt(ret); +} + +Region Region::getIntersectingRegion(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getIntersectingRegion: Regions have different number of dimensions." + ); + + Region ret; + ret.makeInfinite(m_dimension); + + // check for intersection. + // marioh: avoid function call since this is called billions of times. + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (m_pLow[cDim] > r.m_pHigh[cDim] || m_pHigh[cDim] < r.m_pLow[cDim]) return ret; + } + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + ret.m_pLow[cDim] = std::max(m_pLow[cDim], r.m_pLow[cDim]); + ret.m_pHigh[cDim] = std::min(m_pHigh[cDim], r.m_pHigh[cDim]); + } + + return ret; +} + +double Region::getIntersectingArea(const Region& r) const +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getIntersectingArea: Regions have different number of dimensions." + ); + + double ret = 1.0; + double f1, f2; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if (m_pLow[cDim] > r.m_pHigh[cDim] || m_pHigh[cDim] < r.m_pLow[cDim]) return 0.0; + + f1 = std::max(m_pLow[cDim], r.m_pLow[cDim]); + f2 = std::min(m_pHigh[cDim], r.m_pHigh[cDim]); + ret *= f2 - f1; + } + + return ret; +} + +/* + * Returns the margin of a region. It is calcuated as the sum of 2^(d-1) * width, in each dimension. + * It is actually the sum of all edges, no matter what the dimensionality is. +*/ +double Region::getMargin() const +{ + double mul = std::pow(2.0, static_cast<double>(m_dimension) - 1.0); + double margin = 0.0; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + margin += (m_pHigh[i] - m_pLow[i]) * mul; + } + + return margin; +} + +void Region::combineRegion(const Region& r) +{ + if (m_dimension != r.m_dimension) + throw Tools::IllegalArgumentException( + "Region::combineRegion: Region has different number of dimensions." + ); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(m_pLow[cDim], r.m_pLow[cDim]); + m_pHigh[cDim] = std::max(m_pHigh[cDim], r.m_pHigh[cDim]); + } +} + +void Region::combinePoint(const Point& p) +{ + if (m_dimension != p.m_dimension) + throw Tools::IllegalArgumentException( + "Region::combinePoint: Point has different number of dimensions." + ); + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + m_pLow[cDim] = std::min(m_pLow[cDim], p.m_pCoords[cDim]); + m_pHigh[cDim] = std::max(m_pHigh[cDim], p.m_pCoords[cDim]); + } +} + +void Region::getCombinedRegion(Region& out, const Region& in) const +{ + if (m_dimension != in.m_dimension) + throw Tools::IllegalArgumentException( + "Region::getCombinedRegion: Regions have different number of dimensions." + ); + + out = *this; + out.combineRegion(in); +} + +double Region::getLow(uint32_t index) const +{ + if (index < 0 || index >= m_dimension) + throw Tools::IndexOutOfBoundsException(index); + + return m_pLow[index]; +} + +double Region::getHigh(uint32_t index) const +{ + if (index < 0 || index >= m_dimension) + throw Tools::IndexOutOfBoundsException(index); + + return m_pHigh[index]; +} + +void Region::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pLow[cIndex] = std::numeric_limits<double>::max(); + m_pHigh[cIndex] = -std::numeric_limits<double>::max(); + } +} + +void Region::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + delete[] m_pLow; + delete[] m_pHigh; + + // remember that this is not a constructor. The object will be destructed normally if + // something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state. + m_pLow = 0; m_pHigh = 0; + + m_dimension = dimension; + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const Region& r) +{ + uint32_t i; + + os << "Low: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pLow[i] << " "; + } + + os << ", High: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pHigh[i] << " "; + } + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/SpatialIndexImpl.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/SpatialIndexImpl.cc new file mode 100644 index 000000000..9d2bd11aa --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/SpatialIndexImpl.cc @@ -0,0 +1,93 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "SpatialIndexImpl.h" + +#include "../rtree/RTree.h" +#include "../mvrtree/MVRTree.h" +#include "../tprtree/TPRTree.h" + +SpatialIndex::InvalidPageException::InvalidPageException(id_type id) +{ + std::ostringstream s; + s << "Unknown page id " << id; + m_error = s.str(); +} + +std::string SpatialIndex::InvalidPageException::what() +{ + return "InvalidPageException: " + m_error; +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const ISpatialIndex& i) +{ + const SpatialIndex::RTree::RTree* pRTree = dynamic_cast<const SpatialIndex::RTree::RTree*>(&i); + if (pRTree != 0) + { + os << *pRTree; + return os; + } + + const SpatialIndex::MVRTree::MVRTree* pMVRTree = dynamic_cast<const SpatialIndex::MVRTree::MVRTree*>(&i); + if (pMVRTree != 0) + { + os << *pMVRTree; + return os; + } + + const SpatialIndex::TPRTree::TPRTree* pTPRTree = dynamic_cast<const SpatialIndex::TPRTree::TPRTree*>(&i); + if (pTPRTree != 0) + { + os << *pTPRTree; + return os; + } + + std::cerr << "ISpatialIndex operator<<: Not implemented yet for this index type." << std::endl; + return os; +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const IStatistics& s) +{ + const SpatialIndex::RTree::Statistics* pRTreeStats = dynamic_cast<const SpatialIndex::RTree::Statistics*>(&s); + if (pRTreeStats != 0) + { + os << *pRTreeStats; + return os; + } + + const SpatialIndex::MVRTree::Statistics* pMVRTreeStats = dynamic_cast<const SpatialIndex::MVRTree::Statistics*>(&s); + if (pMVRTreeStats != 0) + { + os << * pMVRTreeStats; + return os; + } + + const SpatialIndex::TPRTree::Statistics* pTPRTreeStats = dynamic_cast<const SpatialIndex::TPRTree::Statistics*>(&s); + if (pTPRTreeStats != 0) + { + os << * pTPRTreeStats; + return os; + } + + std::cerr << "IStatistics operator<<: Not implemented yet for this index type." << std::endl; + return os; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/SpatialIndexImpl.h b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/SpatialIndexImpl.h new file mode 100644 index 000000000..5a24bbc6e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/SpatialIndexImpl.h @@ -0,0 +1,32 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +typedef Tools::PoolPointer<Region> RegionPtr; +typedef Tools::PoolPointer<Point> PointPtr; +typedef Tools::PoolPointer<TimeRegion> TimeRegionPtr; +typedef Tools::PoolPointer<MovingRegion> MovingRegionPtr; + diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/TimePoint.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/TimePoint.cc new file mode 100644 index 000000000..d860a0168 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/TimePoint.cc @@ -0,0 +1,297 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <limits> + +#include "../../include/SpatialIndex.h" + +using namespace SpatialIndex; + +TimePoint::TimePoint() + : Point(), m_startTime(-std::numeric_limits<double>::max()), m_endTime(std::numeric_limits<double>::max()) +{ +} + +TimePoint::TimePoint(const double* pCoords, const IInterval& ti, uint32_t dimension) + : Point(pCoords, dimension), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimePoint::TimePoint(const double* pCoords, double tStart, double tEnd, uint32_t dimension) + : Point(pCoords, dimension), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimePoint::TimePoint(const Point& p, const IInterval& ti) + : Point(p), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimePoint::TimePoint(const Point& p, double tStart, double tEnd) + : Point(p), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimePoint::TimePoint(const TimePoint& p) + : m_startTime(p.m_startTime), m_endTime(p.m_endTime) +{ + m_dimension = p.m_dimension; + + m_pCoords = new double[m_dimension]; + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); +} + +TimePoint::~TimePoint() +{ +} + +TimePoint& TimePoint::operator=(const TimePoint& p) +{ + if (this != &p) + { + makeDimension(p.m_dimension); + memcpy(m_pCoords, p.m_pCoords, m_dimension * sizeof(double)); + m_startTime = p.m_startTime; + m_endTime = p.m_endTime; + } + + return *this; +} + +bool TimePoint::operator==(const TimePoint& p) const +{ + if ( + m_startTime < p.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > p.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < p.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > p.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t cDim = 0; cDim < m_dimension; ++cDim) + { + if ( + m_pCoords[cDim] < p.m_pCoords[cDim] - std::numeric_limits<double>::epsilon() || + m_pCoords[cDim] > p.m_pCoords[cDim] + std::numeric_limits<double>::epsilon()) + return false; + } + + return true; +} + +// +// IObject interface +// +TimePoint* TimePoint::clone() +{ + return new TimePoint(*this); +} + +// +// ISerializable interface +// +uint32_t TimePoint::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + m_dimension * sizeof(double)); +} + +void TimePoint::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pCoords, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void TimePoint::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, m_pCoords, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// ITimeShape interface +// +bool TimePoint::intersectsShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return pr->containsPointInTime(*this); + + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimePoint::intersectsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimePoint::containsShapeInTime(const ITimeShape& in) const +{ + return false; +} + +bool TimePoint::containsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + return false; +} + +bool TimePoint::touchesShapeInTime(const ITimeShape& in) const +{ + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +bool TimePoint::touchesShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +double TimePoint::getAreaInTime() const +{ + return 0.0; +} + +double TimePoint::getAreaInTime(const IInterval& ivI) const +{ + return 0.0; +} + +double TimePoint::getIntersectingAreaInTime(const ITimeShape& r) const +{ + return 0.0; +} + +double TimePoint::getIntersectingAreaInTime(const IInterval& ivI, const ITimeShape& r) const +{ + return 0.0; +} + +// +// IInterval interface +// +Tools::IInterval& TimePoint::operator=(const Tools::IInterval& i) +{ + if (this != &i) + { + m_startTime = i.getLowerBound(); + m_endTime = i.getUpperBound(); + } + + return *this; +} + +double TimePoint::getLowerBound() const +{ + return m_startTime; +} + +double TimePoint::getUpperBound() const +{ + return m_endTime; +} + +void TimePoint::setBounds(double l, double h) +{ + assert(l <= h); + + m_startTime = l; + m_endTime = h; +} + +bool TimePoint::intersectsInterval(const IInterval& ti) const +{ + return intersectsInterval(ti.getIntervalType(), ti.getLowerBound(), ti.getUpperBound()); +} + +bool TimePoint::intersectsInterval(Tools::IntervalType t, const double start, const double end) const +{ + //if (m_startTime != start && + // (m_startTime >= end || m_endTime <= start)) return false; + if (m_startTime >= end || m_endTime <= start) return false; + + return true; +} + +bool TimePoint::containsInterval(const IInterval& ti) const +{ + if (m_startTime <= ti.getLowerBound() && m_endTime >= ti.getUpperBound()) return true; + return false; +} + +Tools::IntervalType TimePoint::getIntervalType() const +{ + return Tools::IT_RIGHTOPEN; +} + +void TimePoint::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pCoords[cIndex] = std::numeric_limits<double>::max(); + } + + m_startTime = std::numeric_limits<double>::max(); + m_endTime = -std::numeric_limits<double>::max(); +} + +void TimePoint::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + m_dimension = dimension; + + delete[] m_pCoords; + m_pCoords = 0; + + m_pCoords = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const TimePoint& pt) +{ + uint32_t i; + + for (i = 0; i < pt.m_dimension; ++i) + { + os << pt.m_pCoords[i] << " "; + } + + os << ", Start: " << pt.m_startTime << ", End: " << pt.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/spatialindex/TimeRegion.cc b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/TimeRegion.cc new file mode 100644 index 000000000..00d575223 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/spatialindex/TimeRegion.cc @@ -0,0 +1,419 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../../include/SpatialIndex.h" + +#include <cstring> +#include <limits> + +using namespace SpatialIndex; + +TimeRegion::TimeRegion() + : Region(), m_startTime(-std::numeric_limits<double>::max()), m_endTime(std::numeric_limits<double>::max()) +{ +} + +TimeRegion::TimeRegion(const double* pLow, const double* pHigh, const IInterval& ti, uint32_t dimension) + : Region(pLow, pHigh, dimension), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimeRegion::TimeRegion(const double* pLow, const double* pHigh, double tStart, double tEnd, uint32_t dimension) + : Region(pLow, pHigh, dimension), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimeRegion::TimeRegion(const Point& low, const Point& high, const IInterval& ti) + : Region(low, high), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimeRegion::TimeRegion(const Point& low, const Point& high, double tStart, double tEnd) + : Region(low, high), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimeRegion::TimeRegion(const Region& r, const IInterval& ti) + : Region(r), m_startTime(ti.getLowerBound()), m_endTime(ti.getUpperBound()) +{ +} + +TimeRegion::TimeRegion(const Region& r, double tStart, double tEnd) + : Region(r), m_startTime(tStart), m_endTime(tEnd) +{ +} + +TimeRegion::TimeRegion(const TimePoint& low, const TimePoint& high) + : Region((Point&) low, (Point&) high), m_startTime(low.m_startTime), m_endTime(high.m_endTime) +{ +} + +TimeRegion::TimeRegion(const TimeRegion& r) + : m_startTime(r.m_startTime), m_endTime(r.m_endTime) +{ + m_dimension = r.m_dimension; + m_pLow = 0; + + try + { + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } + catch (...) + { + delete[] m_pLow; + throw; + } + + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); +} + +TimeRegion::~TimeRegion() +{ +} + +TimeRegion& TimeRegion::operator=(const TimeRegion& r) +{ + if(this != &r) + { + makeDimension(r.m_dimension); + memcpy(m_pLow, r.m_pLow, m_dimension * sizeof(double)); + memcpy(m_pHigh, r.m_pHigh, m_dimension * sizeof(double)); + + m_startTime = r.m_startTime; + m_endTime = r.m_endTime; + } + + return *this; +} + +bool TimeRegion::operator==(const TimeRegion& r) const +{ + if (m_startTime < r.m_startTime - std::numeric_limits<double>::epsilon() || + m_startTime > r.m_startTime + std::numeric_limits<double>::epsilon() || + m_endTime < r.m_endTime - std::numeric_limits<double>::epsilon() || + m_endTime > r.m_endTime + std::numeric_limits<double>::epsilon()) + return false; + + for (uint32_t i = 0; i < m_dimension; ++i) + { + if ( + m_pLow[i] < r.m_pLow[i] - std::numeric_limits<double>::epsilon() || + m_pLow[i] > r.m_pLow[i] + std::numeric_limits<double>::epsilon() || + m_pHigh[i] < r.m_pHigh[i] - std::numeric_limits<double>::epsilon() || + m_pHigh[i] > r.m_pHigh[i] + std::numeric_limits<double>::epsilon()) + return false; + } + return true; +} + +bool TimeRegion::intersectsRegionInTime(const TimeRegion& r) const +{ + // they should just intersect in time. + // check if they intersect in time first. + // the first check is needed for the following case: + // m_endTime == m_startTime == r.m_startTime. + // For open ended intervals this should be considered as an intersection + // (takes care of degenarate intervals) + //if (m_startTime != r.m_startTime && + // (m_startTime >= r.m_endTime || m_endTime <= r.m_startTime)) + if (! intersectsInterval(r)) return false; + return Region::intersectsRegion(r); +} + +bool TimeRegion::containsRegionInTime(const TimeRegion& r) const +{ + // it should be contained in time. + if (! containsInterval(r)) return false; + return Region::containsRegion(r); +} + +bool TimeRegion::touchesRegionInTime(const TimeRegion& r) const +{ + // they should just intersect in time. + //if (m_startTime != r.m_startTime && + // (m_startTime >= r.m_endTime || m_endTime <= r.m_startTime)) + if (!intersectsInterval(r)) return false; + return Region::touchesRegion(r); +} + +bool TimeRegion::containsPointInTime(const TimePoint& p) const +{ + // it should be contained in time. + //if (p.m_startTime < m_startTime || p.m_endTime > m_endTime) return false; + if (containsInterval(p)) return false; + return Region::containsPoint(p); +} + +bool TimeRegion::touchesPointInTime(const TimePoint& p) const +{ + // they should just intersect in time. + //if (m_startTime != p.m_startTime && + // (m_startTime >= p.m_endTime || m_endTime <= p.m_startTime)) + if (intersectsInterval(p)) return false; + return Region::touchesPoint(p); +} + +void TimeRegion::combineRegionInTime(const TimeRegion& r) +{ + Region::combineRegion(r); + + m_startTime = std::min(m_startTime, r.m_startTime); + m_endTime = std::max(m_endTime, r.m_endTime); +} + +void TimeRegion::getCombinedRegionInTime(TimeRegion& out, const TimeRegion& in) const +{ + Region::getCombinedRegion(out, in); + + out.m_startTime = std::min(m_startTime, in.m_startTime); + out.m_endTime = std::max(m_endTime, in.m_endTime); +} + +// +// IObject interface +// +TimeRegion* TimeRegion::clone() +{ + return new TimeRegion(*this); +} + +// +// ISerializable interface +// +uint32_t TimeRegion::getByteArraySize() +{ + return (sizeof(uint32_t) + 2 * sizeof(double) + 2 * m_dimension * sizeof(double)); +} + +void TimeRegion::loadFromByteArray(const byte* ptr) +{ + uint32_t dimension; + + memcpy(&dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_startTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_endTime, ptr, sizeof(double)); + ptr += sizeof(double); + + makeDimension(dimension); + memcpy(m_pLow, ptr, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(m_pHigh, ptr, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +void TimeRegion::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_startTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_endTime, sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, m_pLow, m_dimension * sizeof(double)); + ptr += m_dimension * sizeof(double); + memcpy(ptr, m_pHigh, m_dimension * sizeof(double)); + //ptr += m_dimension * sizeof(double); +} + +// +// ITimeShape interface +// +bool TimeRegion::intersectsShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return intersectsRegionInTime(*pr); + + const TimePoint* ppt = dynamic_cast<const TimePoint*>(&in); + if (ppt != 0) return containsPointInTime(*ppt); + + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::intersectsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("intersectsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::containsShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return containsRegionInTime(*pr); + + const TimePoint* ppt = dynamic_cast<const TimePoint*>(&in); + if (ppt != 0) return containsPointInTime(*ppt); + + throw Tools::IllegalStateException("containsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::containsShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("containsShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::touchesShapeInTime(const ITimeShape& in) const +{ + const TimeRegion* pr = dynamic_cast<const TimeRegion*>(&in); + if (pr != 0) return touchesRegionInTime(*pr); + + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +bool TimeRegion::touchesShapeInTime(const IInterval& ivI, const ITimeShape& in) const +{ + throw Tools::IllegalStateException("touchesShapeInTime: Not implemented yet!"); +} + +double TimeRegion::getAreaInTime() const +{ + throw Tools::IllegalStateException("getAreaInTime: Not implemented yet!"); +} + +double TimeRegion::getAreaInTime(const IInterval& ivI) const +{ + throw Tools::IllegalStateException("getAreaInTime: Not implemented yet!"); +} + +double TimeRegion::getIntersectingAreaInTime(const ITimeShape& r) const +{ + throw Tools::IllegalStateException("getIntersectingAreaInTime: Not implemented yet!"); +} + +double TimeRegion::getIntersectingAreaInTime(const IInterval& ivI, const ITimeShape& r) const +{ + throw Tools::IllegalStateException("getIntersectingAreaInTime: Not implemented yet!"); +} + +// +// IInterval interface +// +Tools::IInterval& TimeRegion::operator=(const Tools::IInterval& i) +{ + if (this != &i) + { + m_startTime = i.getLowerBound(); + m_endTime = i.getUpperBound(); + } + + return *this; +} + +double TimeRegion::getLowerBound() const +{ + return m_startTime; +} + +double TimeRegion::getUpperBound() const +{ + return m_endTime; +} + +void TimeRegion::setBounds(double l, double h) +{ + assert(m_startTime <= m_endTime); + + m_startTime = l; + m_endTime = h; +} + +bool TimeRegion::intersectsInterval(const IInterval& ti) const +{ + return intersectsInterval(ti.getIntervalType(), ti.getLowerBound(), ti.getUpperBound()); +} + +bool TimeRegion::intersectsInterval(Tools::IntervalType t, const double start, const double end) const +{ + //if (m_startTime != start && + // (m_startTime >= end || m_endTime <= start)) return false; + // this will not work for degenarate intervals. + if (m_startTime >= end || m_endTime <= start) return false; + + return true; +} + +bool TimeRegion::containsInterval(const IInterval& ti) const +{ + if (m_startTime <= ti.getLowerBound() && m_endTime >= ti.getUpperBound()) return true; + return false; +} + +Tools::IntervalType TimeRegion::getIntervalType() const +{ + return Tools::IT_RIGHTOPEN; +} + +void TimeRegion::makeInfinite(uint32_t dimension) +{ + makeDimension(dimension); + for (uint32_t cIndex = 0; cIndex < m_dimension; ++cIndex) + { + m_pLow[cIndex] = std::numeric_limits<double>::max(); + m_pHigh[cIndex] = -std::numeric_limits<double>::max(); + } + + m_startTime = std::numeric_limits<double>::max(); + m_endTime = -std::numeric_limits<double>::max(); +} + +void TimeRegion::makeDimension(uint32_t dimension) +{ + if (m_dimension != dimension) + { + m_dimension = dimension; + + delete[] m_pLow; + delete[] m_pHigh; + m_pLow = 0; m_pHigh = 0; + + m_pLow = new double[m_dimension]; + m_pHigh = new double[m_dimension]; + } +} + +std::ostream& SpatialIndex::operator<<(std::ostream& os, const TimeRegion& r) +{ + uint32_t i; + + os << "Low: "; + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pLow[i] << " "; + } + + os << ", High: "; + + for (i = 0; i < r.m_dimension; ++i) + { + os << r.m_pHigh[i] << " "; + } + + os << ", Start: " << r.m_startTime << ", End: " << r.m_endTime; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/all-wcprops new file mode 100644 index 000000000..4741ee8b7 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/all-wcprops @@ -0,0 +1,59 @@ +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/158/spatialindex/trunk/src/storagemanager +END +Buffer.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/storagemanager/Buffer.h +END +DiskStorageManager.h +K 25 +svn:wc:ra_dav:version-url +V 85 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/storagemanager/DiskStorageManager.h +END +RandomEvictionsBuffer.cc +K 25 +svn:wc:ra_dav:version-url +V 89 +/spatialindex/!svn/ver/158/spatialindex/trunk/src/storagemanager/RandomEvictionsBuffer.cc +END +RandomEvictionsBuffer.h +K 25 +svn:wc:ra_dav:version-url +V 87 +/spatialindex/!svn/ver/99/spatialindex/trunk/src/storagemanager/RandomEvictionsBuffer.h +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 75 +/spatialindex/!svn/ver/45/spatialindex/trunk/src/storagemanager/Makefile.am +END +MemoryStorageManager.cc +K 25 +svn:wc:ra_dav:version-url +V 88 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/storagemanager/MemoryStorageManager.cc +END +Buffer.cc +K 25 +svn:wc:ra_dav:version-url +V 74 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/storagemanager/Buffer.cc +END +DiskStorageManager.cc +K 25 +svn:wc:ra_dav:version-url +V 86 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/storagemanager/DiskStorageManager.cc +END +MemoryStorageManager.h +K 25 +svn:wc:ra_dav:version-url +V 87 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/storagemanager/MemoryStorageManager.h +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/dir-prop-base new file mode 100644 index 000000000..60357233a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/dir-prop-base @@ -0,0 +1,10 @@ +K 10 +svn:ignore +V 34 +Makefile.in +.libs +.deps +Makefile + + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/entries new file mode 100644 index 000000000..3cb6f0abc --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/entries @@ -0,0 +1,334 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/storagemanager +http://svn.gispython.org/spatialindex + + + +2009-10-30T17:09:14.837776Z +158 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Buffer.h +file + + + + +2011-08-01T00:42:34.385378Z +94f2d7e7c44093c7c05f5300ece746c2 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2228 + +DiskStorageManager.h +file + + + + +2011-08-01T00:42:34.385378Z +9bd3718b4137b193929124050414f022 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +1703 + +RandomEvictionsBuffer.cc +file + + + + +2011-08-01T00:42:34.385378Z +18366c036c6b03381b91f110885ff78d +2009-10-30T17:09:14.837776Z +158 +hobu + + + + + + + + + + + + + + + + + + + + + +2719 + +RandomEvictionsBuffer.h +file + + + + +2011-08-01T00:42:34.385378Z +5189e602bc4b650a48215ed1f2ea0a2c +2009-07-18T22:19:07.374702Z +99 +mhadji + + + + + + + + + + + + + + + + + + + + + +1269 + +Makefile.am +file + + + + +2011-08-01T00:42:34.385378Z +d5ec09ef9b0b39266f73187e1d98f5ae +2008-01-17T23:34:01.575758Z +45 +hobu + + + + + + + + + + + + + + + + + + + + + +332 + +MemoryStorageManager.cc +file + + + + +2011-08-01T00:42:34.409261Z +3b94af6eadf797555dc5bbfff0aa716a +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2856 + +Buffer.cc +file + + + + +2011-08-01T00:42:34.409261Z +ea93f0fe41f1d4a84899dbecafec54d8 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +3648 + +DiskStorageManager.cc +file + + + + +2011-08-01T00:42:34.409261Z +79d50b6e39a2b68c61da0777d95bd992 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +15691 + +MemoryStorageManager.h +file + + + + +2011-08-01T00:42:34.409261Z +2696238537d4e8ef56d99755d86ff3e5 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +1708 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Buffer.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Buffer.cc.svn-base new file mode 100644 index 000000000..f605cd0f8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Buffer.cc.svn-base @@ -0,0 +1,142 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include "../spatialindex/SpatialIndexImpl.h" +#include "Buffer.h" + +Buffer::Buffer(IStorageManager& sm, Tools::PropertySet& ps) : + m_capacity(10), + m_bWriteThrough(false), + m_pStorageManager(&sm), + m_u64Hits(0) +{ + Tools::Variant var = ps.getProperty("Capacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("Property Capacity must be Tools::VT_ULONG"); + m_capacity = var.m_val.ulVal; + } + + var = ps.getProperty("WriteThrough"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("Property WriteThrough must be Tools::VT_BOOL"); + m_bWriteThrough = var.m_val.blVal; + } +} + +Buffer::~Buffer() +{ + for (std::map<id_type, Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); ++it) + { + if ((*it).second->m_bDirty) + { + id_type page = (*it).first; + m_pStorageManager->storeByteArray(page, (*it).second->m_length, (*it).second->m_pData); + } + delete (*it).second; + } +} + +void Buffer::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + std::map<id_type, Entry*>::iterator it = m_buffer.find(page); + + if (it != m_buffer.end()) + { + ++m_u64Hits; + len = (*it).second->m_length; + *data = new byte[len]; + memcpy(*data, (*it).second->m_pData, len); + } + else + { + m_pStorageManager->loadByteArray(page, len, data); + addEntry(page, new Entry(len, static_cast<const byte*>(*data))); + } +} + +void Buffer::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + if (page == NewPage) + { + m_pStorageManager->storeByteArray(page, len, data); + assert(m_buffer.find(page) == m_buffer.end()); + addEntry(page, new Entry(len, data)); + } + else + { + if (m_bWriteThrough) + { + m_pStorageManager->storeByteArray(page, len, data); + } + + Entry* e = new Entry(len, data); + if (m_bWriteThrough == false) e->m_bDirty = true; + + std::map<id_type, Entry*>::iterator it = m_buffer.find(page); + if (it != m_buffer.end()) + { + delete (*it).second; + (*it).second = e; + if (m_bWriteThrough == false) ++m_u64Hits; + } + else + { + addEntry(page, e); + } + } +} + +void Buffer::deleteByteArray(const id_type page) +{ + std::map<id_type, Entry*>::iterator it = m_buffer.find(page); + if (it != m_buffer.end()) + { + delete (*it).second; + m_buffer.erase(it); + } + + m_pStorageManager->deleteByteArray(page); +} + +void Buffer::clear() +{ + for (std::map<id_type, Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); ++it) + { + if ((*it).second->m_bDirty) + { + id_type page = (*it).first; + m_pStorageManager->storeByteArray(page, ((*it).second)->m_length, static_cast<const byte*>(((*it).second)->m_pData)); + } + + delete (*it).second; + } + + m_buffer.clear(); + m_u64Hits = 0; +} + +uint64_t Buffer::getHits() +{ + return m_u64Hits; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Buffer.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Buffer.h.svn-base new file mode 100644 index 000000000..450e38a5b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Buffer.h.svn-base @@ -0,0 +1,78 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include <cstring> + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +namespace SpatialIndex +{ + namespace StorageManager + { + class Buffer : public IBuffer + { + public: + Buffer(IStorageManager& sm, Tools::PropertySet& ps); + // String Value Description + // ---------------------------------------------- + // Capacity VT_ULONG Buffer maximum capacity. + // WriteThrough VT_BOOL Enable or disable write through policy. + + virtual ~Buffer(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + virtual void clear(); + virtual uint64_t getHits(); + + protected: + class Entry + { + public: + Entry(uint32_t l, const byte* const d) : m_pData(0), m_length(l), m_bDirty(false) + { + m_pData = new byte[m_length]; + memcpy(m_pData, d, m_length); + } + + ~Entry() { delete[] m_pData; } + + byte* m_pData; + uint32_t m_length; + bool m_bDirty; + }; // Entry + + virtual void addEntry(id_type page, Entry* pEntry) = 0; + virtual void removeEntry() = 0; + + uint32_t m_capacity; + bool m_bWriteThrough; + IStorageManager* m_pStorageManager; + std::map<id_type, Entry*> m_buffer; + uint64_t m_u64Hits; + }; // Buffer + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base new file mode 100644 index 000000000..ecf1c9139 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base @@ -0,0 +1,501 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <fstream> +#include <cstring> + +// For checking if a file exists - hobu +#include <sys/stat.h> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "DiskStorageManager.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +bool CheckFilesExists(Tools::PropertySet& ps) +{ + bool bExists = false; + + std::string filename(""); + std::string idx("idx"); + std::string dat("dat"); + + Tools::Variant idx_name; + Tools::Variant dat_name; + Tools::Variant fn; + + idx_name = ps.getProperty("FileNameIdx"); + dat_name = ps.getProperty("FileNameDat"); + fn = ps.getProperty("FileName"); + + if (idx_name.m_varType != Tools::VT_EMPTY) dat = std::string(idx_name.m_val.pcVal); + if (dat_name.m_varType != Tools::VT_EMPTY) idx = std::string(dat_name.m_val.pcVal); + if (fn.m_varType != Tools::VT_EMPTY) filename = std::string(fn.m_val.pcVal); + + struct stat stats; + + std::ostringstream os; + int ret; + os << filename <<"."<<dat; + std::string data_name = os.str(); + ret = stat(data_name.c_str(), &stats); + + if (ret == 0) bExists = true; + + os.str(""); + os << filename <<"."<<idx; + std::string index_name = os.str(); + ret = stat(index_name.c_str(), &stats); + + if ((ret == 0) && (bExists == true)) bExists = true; + + return bExists; +} +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnDiskStorageManager(Tools::PropertySet& ps) +{ + IStorageManager* sm = new DiskStorageManager(ps); + return sm; +} + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewDiskStorageManager(std::string& baseName, uint32_t pageSize) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = true; + ps.setProperty("Overwrite", var); + // overwrite the file if it exists. + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>(baseName.c_str()); + ps.setProperty("FileName", var); + // .idx and .dat extensions will be added. + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = pageSize; + ps.setProperty("PageSize", var); + // specify the page size. Since the index may also contain user defined data + // there is no way to know how big a single node may become. The storage manager + // will use multiple pages per node if needed. Off course this will slow down performance. + + return returnDiskStorageManager(ps); +} + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::loadDiskStorageManager(std::string& baseName) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>(baseName.c_str()); + ps.setProperty("FileName", var); + // .idx and .dat extensions will be added. + + return returnDiskStorageManager(ps); +} + +DiskStorageManager::DiskStorageManager(Tools::PropertySet& ps) : m_pageSize(0), m_nextPage(-1), m_buffer(0) +{ + Tools::Variant var; + + // Open/Create flag. + bool bOverwrite = false; + var = ps.getProperty("Overwrite"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property Overwrite must be Tools::VT_BOOL"); + bOverwrite = var.m_val.blVal; + } + + // storage filename. + var = ps.getProperty("FileName"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property FileName must be Tools::VT_PCHAR"); + + std::string idx("idx"); + std::string dat("dat"); + + Tools::Variant idx_name = ps.getProperty("FileNameIdx"); + if (idx_name.m_varType != Tools::VT_EMPTY) idx = std::string(idx_name.m_val.pcVal); + + Tools::Variant dat_name = ps.getProperty("FileNameDat"); + if (dat_name.m_varType != Tools::VT_EMPTY) dat = std::string(dat_name.m_val.pcVal); + + std::string sIndexFile = std::string(var.m_val.pcVal) + "." + idx; + std::string sDataFile = std::string(var.m_val.pcVal) + "." + dat; + + // check if file exists. + bool bFileExists = CheckFilesExists(ps); + + // check if file can be read/written. + if (bFileExists == true && bOverwrite == false) + { + m_indexFile.open(sIndexFile.c_str(), std::ios::in | std::ios::out | std::ios::binary); + m_dataFile.open(sDataFile.c_str(), std::ios::in | std::ios::out | std::ios::binary); + + if (m_indexFile.fail() || m_dataFile.fail()) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Index/Data file cannot be read/writen."); + } + else + { + m_indexFile.open(sIndexFile.c_str(), std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc); + m_dataFile.open(sDataFile.c_str(), std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc); + + if (m_indexFile.fail() || m_dataFile.fail()) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Index/Data file cannot be created."); + + } + } + else + { + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property FileName was not specified."); + } + + // find page size. + if (bOverwrite == true) + { + var = ps.getProperty("PageSize"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property PageSize must be Tools::VT_ULONG"); + m_pageSize = var.m_val.ulVal; + m_nextPage = 0; + } + else + { + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: A new storage manager is created and property PageSize was not specified."); + } + } + else + { + m_indexFile.read(reinterpret_cast<char*>(&m_pageSize), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Failed reading pageSize."); + + m_indexFile.read(reinterpret_cast<char*>(&m_nextPage), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Failed reading nextPage."); + } + + // create buffer. + m_buffer = new byte[m_pageSize]; + bzero(m_buffer, m_pageSize); + + if (bOverwrite == false) + { + uint32_t count; + id_type page, id; + + // load empty pages in memory. + m_indexFile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cCount = 0; cCount < count; ++cCount) + { + m_indexFile.read(reinterpret_cast<char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + m_emptyPages.push(page); + } + + // load index table in memory. + m_indexFile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cCount = 0; cCount < count; ++cCount) + { + Entry* e = new Entry(); + + m_indexFile.read(reinterpret_cast<char*>(&id), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + m_indexFile.read(reinterpret_cast<char*>(&(e->m_length)), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + uint32_t count2; + m_indexFile.read(reinterpret_cast<char*>(&count2), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cCount2 = 0; cCount2 < count2; ++cCount2) + { + m_indexFile.read(reinterpret_cast<char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + e->m_pages.push_back(page); + } + m_pageIndex.insert(std::pair<id_type, Entry* >(id, e)); + } + } +} + +DiskStorageManager::~DiskStorageManager() +{ + flush(); + m_indexFile.close(); + m_dataFile.close(); + if (m_buffer != 0) delete[] m_buffer; + + std::map<id_type, Entry*>::iterator it; + for (it = m_pageIndex.begin(); it != m_pageIndex.end(); ++it) delete (*it).second; +} + +void DiskStorageManager::flush() +{ + m_indexFile.seekp(0, std::ios_base::beg); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + m_indexFile.write(reinterpret_cast<const char*>(&m_pageSize), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + m_indexFile.write(reinterpret_cast<const char*>(&m_nextPage), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + uint32_t count = static_cast<uint32_t>(m_emptyPages.size()); + id_type page, id; + + m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + while (! m_emptyPages.empty()) + { + page = m_emptyPages.top(); m_emptyPages.pop(); + m_indexFile.write(reinterpret_cast<const char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + } + + count = static_cast<uint32_t>(m_pageIndex.size()); + + m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + std::map<id_type, Entry*>::iterator it; + + for (it = m_pageIndex.begin(); it != m_pageIndex.end(); ++it) + { + id = (*it).first; + m_indexFile.write(reinterpret_cast<const char*>(&id), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + uint32_t length = (*it).second->m_length; + m_indexFile.write(reinterpret_cast<const char*>(&length), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + count = static_cast<uint32_t>((*it).second->m_pages.size()); + m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cIndex = 0; cIndex < count; ++cIndex) + { + page = (*it).second->m_pages[cIndex]; + m_indexFile.write(reinterpret_cast<const char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + } + } + + m_indexFile.flush(); + m_dataFile.flush(); +} + +void DiskStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page); + + if (it == m_pageIndex.end()) + throw InvalidPageException(page); + + std::vector<id_type>& pages = (*it).second->m_pages; + uint32_t cNext = 0; + uint32_t cTotal = static_cast<uint32_t>(pages.size()); + + len = (*it).second->m_length; + *data = new byte[len]; + + byte* ptr = *data; + uint32_t cLen; + uint32_t cRem = len; + + do + { + m_dataFile.seekg(pages[cNext] * m_pageSize, std::ios_base::beg); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + m_dataFile.read(reinterpret_cast<char*>(m_buffer), m_pageSize); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + cLen = (cRem > m_pageSize) ? m_pageSize : cRem; + memcpy(ptr, m_buffer, cLen); + + ptr += cLen; + cRem -= cLen; + ++cNext; + } + while (cNext < cTotal); +} + +void DiskStorageManager::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + if (page == NewPage) + { + Entry* e = new Entry(); + e->m_length = len; + + const byte* ptr = data; + id_type cPage; + uint32_t cRem = len; + uint32_t cLen; + + while (cRem > 0) + { + if (! m_emptyPages.empty()) + { + cPage = m_emptyPages.top(); m_emptyPages.pop(); + } + else + { + cPage = m_nextPage; + ++m_nextPage; + } + + cLen = (cRem > m_pageSize) ? m_pageSize : cRem; + memcpy(m_buffer, ptr, cLen); + + m_dataFile.seekp(cPage * m_pageSize, std::ios_base::beg); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + m_dataFile.write(reinterpret_cast<const char*>(m_buffer), m_pageSize); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + ptr += cLen; + cRem -= cLen; + e->m_pages.push_back(cPage); + } + + page = e->m_pages[0]; + m_pageIndex.insert(std::pair<id_type, Entry*>(page, e)); + } + else + { + // find the entry. + std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page); + + // check if it exists. + if (it == m_pageIndex.end()) + throw InvalidPageException(page); + + Entry* oldEntry = (*it).second; + + m_pageIndex.erase(it); + + Entry* e = new Entry(); + e->m_length = len; + + const byte* ptr = data; + id_type cPage; + uint32_t cRem = len; + uint32_t cLen, cNext = 0; + + while (cRem > 0) + { + if (cNext < oldEntry->m_pages.size()) + { + cPage = oldEntry->m_pages[cNext]; + ++cNext; + } + else if (! m_emptyPages.empty()) + { + cPage = m_emptyPages.top(); m_emptyPages.pop(); + } + else + { + cPage = m_nextPage; + ++m_nextPage; + } + + cLen = (cRem > m_pageSize) ? m_pageSize : cRem; + memcpy(m_buffer, ptr, cLen); + + m_dataFile.seekp(cPage * m_pageSize, std::ios_base::beg); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + m_dataFile.write(reinterpret_cast<const char*>(m_buffer), m_pageSize); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + ptr += cLen; + cRem -= cLen; + e->m_pages.push_back(cPage); + } + + while (cNext < oldEntry->m_pages.size()) + { + m_emptyPages.push(oldEntry->m_pages[cNext]); + ++cNext; + } + + m_pageIndex.insert(std::pair<id_type, Entry*>(page, e)); + delete oldEntry; + } +} + +void DiskStorageManager::deleteByteArray(const id_type page) +{ + std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page); + + if (it == m_pageIndex.end()) + throw InvalidPageException(page); + + for (uint32_t cIndex = 0; cIndex < (*it).second->m_pages.size(); ++cIndex) + { + m_emptyPages.push((*it).second->m_pages[cIndex]); + } + + delete (*it).second; + m_pageIndex.erase(it); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.h.svn-base new file mode 100644 index 000000000..178eb684e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.h.svn-base @@ -0,0 +1,58 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace StorageManager + { + class DiskStorageManager : public SpatialIndex::IStorageManager + { + public: + DiskStorageManager(Tools::PropertySet&); + virtual ~DiskStorageManager(); + + void flush(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + private: + class Entry + { + public: + uint32_t m_length; + std::vector<id_type> m_pages; + }; + + std::fstream m_dataFile; + std::fstream m_indexFile; + uint32_t m_pageSize; + id_type m_nextPage; + std::priority_queue<id_type, std::vector<id_type>, std::greater<id_type> > m_emptyPages; + std::map<id_type, Entry*> m_pageIndex; + + byte* m_buffer; + }; // DiskStorageManager + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..430ab3dac --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libstoragemanager.la +INCLUDES = -I../../include +libstoragemanager_la_SOURCES = Buffer.h Buffer.cc DiskStorageManager.cc MemoryStorageManager.cc RandomEvictionsBuffer.cc DiskStorageManager.h MemoryStorageManager.h RandomEvictionsBuffer.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/MemoryStorageManager.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/MemoryStorageManager.cc.svn-base new file mode 100644 index 000000000..24ef0e04b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/MemoryStorageManager.cc.svn-base @@ -0,0 +1,126 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <stdexcept> +#include <cstring> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MemoryStorageManager.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnMemoryStorageManager(Tools::PropertySet& ps) +{ + IStorageManager* sm = new MemoryStorageManager(ps); + return sm; +} + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewMemoryStorageManager() +{ + Tools::PropertySet ps; + return returnMemoryStorageManager(ps); +} + +MemoryStorageManager::MemoryStorageManager(Tools::PropertySet& ps) +{ +} + +MemoryStorageManager::~MemoryStorageManager() +{ + for (std::vector<Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); ++it) delete *it; +} + +void MemoryStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + Entry* e; + try + { + e = m_buffer.at(page); + if (e == 0) throw InvalidPageException(page); + } + catch (std::out_of_range) + { + throw InvalidPageException(page); + } + + len = e->m_length; + *data = new byte[len]; + + memcpy(*data, e->m_pData, len); +} + +void MemoryStorageManager::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + if (page == NewPage) + { + Entry* e = new Entry(len, data); + + if (m_emptyPages.empty()) + { + m_buffer.push_back(e); + page = m_buffer.size() - 1; + } + else + { + page = m_emptyPages.top(); m_emptyPages.pop(); + m_buffer[page] = e; + } + } + else + { + Entry* e_old; + try + { + e_old = m_buffer.at(page); + if (e_old == 0) throw InvalidPageException(page); + } + catch (std::out_of_range) + { + throw InvalidPageException(page); + } + + Entry* e = new Entry(len, data); + + delete e_old; + m_buffer[page] = e; + } +} + +void MemoryStorageManager::deleteByteArray(const id_type page) +{ + Entry* e; + try + { + e = m_buffer.at(page); + if (e == 0) throw InvalidPageException(page); + } + catch (std::out_of_range) + { + throw InvalidPageException(page); + } + + m_buffer[page] = 0; + m_emptyPages.push(page); + + delete e; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/MemoryStorageManager.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/MemoryStorageManager.h.svn-base new file mode 100644 index 000000000..61a224d80 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/MemoryStorageManager.h.svn-base @@ -0,0 +1,61 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include <cstring> + +namespace SpatialIndex +{ + namespace StorageManager + { + class MemoryStorageManager : public SpatialIndex::IStorageManager + { + public: + MemoryStorageManager(Tools::PropertySet&); + + virtual ~MemoryStorageManager(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + private: + class Entry + { + public: + byte* m_pData; + uint32_t m_length; + + Entry(uint32_t l, const byte* const d) : m_pData(0), m_length(l) + { + m_pData = new byte[m_length]; + memcpy(m_pData, d, m_length); + } + + ~Entry() { delete[] m_pData; } + }; // Entry + + std::vector<Entry*> m_buffer; + std::stack<id_type> m_emptyPages; + }; // MemoryStorageManager + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/RandomEvictionsBuffer.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/RandomEvictionsBuffer.cc.svn-base new file mode 100644 index 000000000..e0e22d296 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/RandomEvictionsBuffer.cc.svn-base @@ -0,0 +1,94 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <time.h> +#include <stdlib.h> +#include <cmath> +#include "../../include/tools/rand48.h" + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RandomEvictionsBuffer.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +IBuffer* SpatialIndex::StorageManager::returnRandomEvictionsBuffer(IStorageManager& sm, Tools::PropertySet& ps) +{ + IBuffer* b = new RandomEvictionsBuffer(sm, ps); + return b; +} + +IBuffer* SpatialIndex::StorageManager::createNewRandomEvictionsBuffer(IStorageManager& sm, uint32_t capacity, bool bWriteThrough) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = capacity; + ps.setProperty("Capacity", var); + + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = bWriteThrough; + ps.setProperty("WriteThrough", var); + + return returnRandomEvictionsBuffer(sm, ps); +} + +RandomEvictionsBuffer::RandomEvictionsBuffer(IStorageManager& sm, Tools::PropertySet& ps) : Buffer(sm, ps) +{ + srand48(static_cast<uint32_t>(time(0))); +} + +RandomEvictionsBuffer::~RandomEvictionsBuffer() +{ +} + +void RandomEvictionsBuffer::addEntry(id_type page, Entry* e) +{ + assert(m_buffer.size() <= m_capacity); + + if (m_buffer.size() == m_capacity) removeEntry(); + assert(m_buffer.find(page) == m_buffer.end()); + m_buffer.insert(std::pair<id_type, Entry*>(page, e)); +} + +void RandomEvictionsBuffer::removeEntry() +{ + if (m_buffer.size() == 0) return; + + double random; + + random = drand48(); + + uint32_t entry = static_cast<uint32_t>(floor(((double) m_buffer.size()) * random)); + + std::map<id_type, Entry*>::iterator it = m_buffer.begin(); + for (uint32_t cIndex = 0; cIndex < entry; cIndex++) ++it; + + if ((*it).second->m_bDirty) + { + id_type page = (*it).first; + m_pStorageManager->storeByteArray(page, ((*it).second)->m_length, (const byte *) ((*it).second)->m_pData); + } + + delete (*it).second; + m_buffer.erase(it); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/RandomEvictionsBuffer.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/RandomEvictionsBuffer.h.svn-base new file mode 100644 index 000000000..64f26681c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/RandomEvictionsBuffer.h.svn-base @@ -0,0 +1,42 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Buffer.h" + +namespace SpatialIndex +{ + namespace StorageManager + { + class RandomEvictionsBuffer : public Buffer + { + public: + RandomEvictionsBuffer(IStorageManager&, Tools::PropertySet& ps); + // see Buffer.h for available properties. + + virtual ~RandomEvictionsBuffer(); + + virtual void addEntry(id_type page, Buffer::Entry* pEntry); + virtual void removeEntry(); + }; // RandomEvictionsBuffer + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Buffer.cc b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Buffer.cc new file mode 100644 index 000000000..f605cd0f8 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Buffer.cc @@ -0,0 +1,142 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include "../spatialindex/SpatialIndexImpl.h" +#include "Buffer.h" + +Buffer::Buffer(IStorageManager& sm, Tools::PropertySet& ps) : + m_capacity(10), + m_bWriteThrough(false), + m_pStorageManager(&sm), + m_u64Hits(0) +{ + Tools::Variant var = ps.getProperty("Capacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("Property Capacity must be Tools::VT_ULONG"); + m_capacity = var.m_val.ulVal; + } + + var = ps.getProperty("WriteThrough"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("Property WriteThrough must be Tools::VT_BOOL"); + m_bWriteThrough = var.m_val.blVal; + } +} + +Buffer::~Buffer() +{ + for (std::map<id_type, Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); ++it) + { + if ((*it).second->m_bDirty) + { + id_type page = (*it).first; + m_pStorageManager->storeByteArray(page, (*it).second->m_length, (*it).second->m_pData); + } + delete (*it).second; + } +} + +void Buffer::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + std::map<id_type, Entry*>::iterator it = m_buffer.find(page); + + if (it != m_buffer.end()) + { + ++m_u64Hits; + len = (*it).second->m_length; + *data = new byte[len]; + memcpy(*data, (*it).second->m_pData, len); + } + else + { + m_pStorageManager->loadByteArray(page, len, data); + addEntry(page, new Entry(len, static_cast<const byte*>(*data))); + } +} + +void Buffer::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + if (page == NewPage) + { + m_pStorageManager->storeByteArray(page, len, data); + assert(m_buffer.find(page) == m_buffer.end()); + addEntry(page, new Entry(len, data)); + } + else + { + if (m_bWriteThrough) + { + m_pStorageManager->storeByteArray(page, len, data); + } + + Entry* e = new Entry(len, data); + if (m_bWriteThrough == false) e->m_bDirty = true; + + std::map<id_type, Entry*>::iterator it = m_buffer.find(page); + if (it != m_buffer.end()) + { + delete (*it).second; + (*it).second = e; + if (m_bWriteThrough == false) ++m_u64Hits; + } + else + { + addEntry(page, e); + } + } +} + +void Buffer::deleteByteArray(const id_type page) +{ + std::map<id_type, Entry*>::iterator it = m_buffer.find(page); + if (it != m_buffer.end()) + { + delete (*it).second; + m_buffer.erase(it); + } + + m_pStorageManager->deleteByteArray(page); +} + +void Buffer::clear() +{ + for (std::map<id_type, Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); ++it) + { + if ((*it).second->m_bDirty) + { + id_type page = (*it).first; + m_pStorageManager->storeByteArray(page, ((*it).second)->m_length, static_cast<const byte*>(((*it).second)->m_pData)); + } + + delete (*it).second; + } + + m_buffer.clear(); + m_u64Hits = 0; +} + +uint64_t Buffer::getHits() +{ + return m_u64Hits; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Buffer.h b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Buffer.h new file mode 100644 index 000000000..450e38a5b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Buffer.h @@ -0,0 +1,78 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include <cstring> + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +namespace SpatialIndex +{ + namespace StorageManager + { + class Buffer : public IBuffer + { + public: + Buffer(IStorageManager& sm, Tools::PropertySet& ps); + // String Value Description + // ---------------------------------------------- + // Capacity VT_ULONG Buffer maximum capacity. + // WriteThrough VT_BOOL Enable or disable write through policy. + + virtual ~Buffer(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + virtual void clear(); + virtual uint64_t getHits(); + + protected: + class Entry + { + public: + Entry(uint32_t l, const byte* const d) : m_pData(0), m_length(l), m_bDirty(false) + { + m_pData = new byte[m_length]; + memcpy(m_pData, d, m_length); + } + + ~Entry() { delete[] m_pData; } + + byte* m_pData; + uint32_t m_length; + bool m_bDirty; + }; // Entry + + virtual void addEntry(id_type page, Entry* pEntry) = 0; + virtual void removeEntry() = 0; + + uint32_t m_capacity; + bool m_bWriteThrough; + IStorageManager* m_pStorageManager; + std::map<id_type, Entry*> m_buffer; + uint64_t m_u64Hits; + }; // Buffer + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/DiskStorageManager.cc b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/DiskStorageManager.cc new file mode 100644 index 000000000..ecf1c9139 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/DiskStorageManager.cc @@ -0,0 +1,501 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <fstream> +#include <cstring> + +// For checking if a file exists - hobu +#include <sys/stat.h> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "DiskStorageManager.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +bool CheckFilesExists(Tools::PropertySet& ps) +{ + bool bExists = false; + + std::string filename(""); + std::string idx("idx"); + std::string dat("dat"); + + Tools::Variant idx_name; + Tools::Variant dat_name; + Tools::Variant fn; + + idx_name = ps.getProperty("FileNameIdx"); + dat_name = ps.getProperty("FileNameDat"); + fn = ps.getProperty("FileName"); + + if (idx_name.m_varType != Tools::VT_EMPTY) dat = std::string(idx_name.m_val.pcVal); + if (dat_name.m_varType != Tools::VT_EMPTY) idx = std::string(dat_name.m_val.pcVal); + if (fn.m_varType != Tools::VT_EMPTY) filename = std::string(fn.m_val.pcVal); + + struct stat stats; + + std::ostringstream os; + int ret; + os << filename <<"."<<dat; + std::string data_name = os.str(); + ret = stat(data_name.c_str(), &stats); + + if (ret == 0) bExists = true; + + os.str(""); + os << filename <<"."<<idx; + std::string index_name = os.str(); + ret = stat(index_name.c_str(), &stats); + + if ((ret == 0) && (bExists == true)) bExists = true; + + return bExists; +} +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnDiskStorageManager(Tools::PropertySet& ps) +{ + IStorageManager* sm = new DiskStorageManager(ps); + return sm; +} + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewDiskStorageManager(std::string& baseName, uint32_t pageSize) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = true; + ps.setProperty("Overwrite", var); + // overwrite the file if it exists. + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>(baseName.c_str()); + ps.setProperty("FileName", var); + // .idx and .dat extensions will be added. + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = pageSize; + ps.setProperty("PageSize", var); + // specify the page size. Since the index may also contain user defined data + // there is no way to know how big a single node may become. The storage manager + // will use multiple pages per node if needed. Off course this will slow down performance. + + return returnDiskStorageManager(ps); +} + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::loadDiskStorageManager(std::string& baseName) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_PCHAR; + var.m_val.pcVal = const_cast<char*>(baseName.c_str()); + ps.setProperty("FileName", var); + // .idx and .dat extensions will be added. + + return returnDiskStorageManager(ps); +} + +DiskStorageManager::DiskStorageManager(Tools::PropertySet& ps) : m_pageSize(0), m_nextPage(-1), m_buffer(0) +{ + Tools::Variant var; + + // Open/Create flag. + bool bOverwrite = false; + var = ps.getProperty("Overwrite"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property Overwrite must be Tools::VT_BOOL"); + bOverwrite = var.m_val.blVal; + } + + // storage filename. + var = ps.getProperty("FileName"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_PCHAR) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property FileName must be Tools::VT_PCHAR"); + + std::string idx("idx"); + std::string dat("dat"); + + Tools::Variant idx_name = ps.getProperty("FileNameIdx"); + if (idx_name.m_varType != Tools::VT_EMPTY) idx = std::string(idx_name.m_val.pcVal); + + Tools::Variant dat_name = ps.getProperty("FileNameDat"); + if (dat_name.m_varType != Tools::VT_EMPTY) dat = std::string(dat_name.m_val.pcVal); + + std::string sIndexFile = std::string(var.m_val.pcVal) + "." + idx; + std::string sDataFile = std::string(var.m_val.pcVal) + "." + dat; + + // check if file exists. + bool bFileExists = CheckFilesExists(ps); + + // check if file can be read/written. + if (bFileExists == true && bOverwrite == false) + { + m_indexFile.open(sIndexFile.c_str(), std::ios::in | std::ios::out | std::ios::binary); + m_dataFile.open(sDataFile.c_str(), std::ios::in | std::ios::out | std::ios::binary); + + if (m_indexFile.fail() || m_dataFile.fail()) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Index/Data file cannot be read/writen."); + } + else + { + m_indexFile.open(sIndexFile.c_str(), std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc); + m_dataFile.open(sDataFile.c_str(), std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc); + + if (m_indexFile.fail() || m_dataFile.fail()) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Index/Data file cannot be created."); + + } + } + else + { + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property FileName was not specified."); + } + + // find page size. + if (bOverwrite == true) + { + var = ps.getProperty("PageSize"); + + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Property PageSize must be Tools::VT_ULONG"); + m_pageSize = var.m_val.ulVal; + m_nextPage = 0; + } + else + { + throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: A new storage manager is created and property PageSize was not specified."); + } + } + else + { + m_indexFile.read(reinterpret_cast<char*>(&m_pageSize), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Failed reading pageSize."); + + m_indexFile.read(reinterpret_cast<char*>(&m_nextPage), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Failed reading nextPage."); + } + + // create buffer. + m_buffer = new byte[m_pageSize]; + bzero(m_buffer, m_pageSize); + + if (bOverwrite == false) + { + uint32_t count; + id_type page, id; + + // load empty pages in memory. + m_indexFile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cCount = 0; cCount < count; ++cCount) + { + m_indexFile.read(reinterpret_cast<char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + m_emptyPages.push(page); + } + + // load index table in memory. + m_indexFile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cCount = 0; cCount < count; ++cCount) + { + Entry* e = new Entry(); + + m_indexFile.read(reinterpret_cast<char*>(&id), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + m_indexFile.read(reinterpret_cast<char*>(&(e->m_length)), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + uint32_t count2; + m_indexFile.read(reinterpret_cast<char*>(&count2), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cCount2 = 0; cCount2 < count2; ++cCount2) + { + m_indexFile.read(reinterpret_cast<char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + e->m_pages.push_back(page); + } + m_pageIndex.insert(std::pair<id_type, Entry* >(id, e)); + } + } +} + +DiskStorageManager::~DiskStorageManager() +{ + flush(); + m_indexFile.close(); + m_dataFile.close(); + if (m_buffer != 0) delete[] m_buffer; + + std::map<id_type, Entry*>::iterator it; + for (it = m_pageIndex.begin(); it != m_pageIndex.end(); ++it) delete (*it).second; +} + +void DiskStorageManager::flush() +{ + m_indexFile.seekp(0, std::ios_base::beg); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + m_indexFile.write(reinterpret_cast<const char*>(&m_pageSize), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + m_indexFile.write(reinterpret_cast<const char*>(&m_nextPage), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + uint32_t count = static_cast<uint32_t>(m_emptyPages.size()); + id_type page, id; + + m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + while (! m_emptyPages.empty()) + { + page = m_emptyPages.top(); m_emptyPages.pop(); + m_indexFile.write(reinterpret_cast<const char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + } + + count = static_cast<uint32_t>(m_pageIndex.size()); + + m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + std::map<id_type, Entry*>::iterator it; + + for (it = m_pageIndex.begin(); it != m_pageIndex.end(); ++it) + { + id = (*it).first; + m_indexFile.write(reinterpret_cast<const char*>(&id), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + uint32_t length = (*it).second->m_length; + m_indexFile.write(reinterpret_cast<const char*>(&length), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + count = static_cast<uint32_t>((*it).second->m_pages.size()); + m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + + for (uint32_t cIndex = 0; cIndex < count; ++cIndex) + { + page = (*it).second->m_pages[cIndex]; + m_indexFile.write(reinterpret_cast<const char*>(&page), sizeof(id_type)); + if (m_indexFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file."); + } + } + + m_indexFile.flush(); + m_dataFile.flush(); +} + +void DiskStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page); + + if (it == m_pageIndex.end()) + throw InvalidPageException(page); + + std::vector<id_type>& pages = (*it).second->m_pages; + uint32_t cNext = 0; + uint32_t cTotal = static_cast<uint32_t>(pages.size()); + + len = (*it).second->m_length; + *data = new byte[len]; + + byte* ptr = *data; + uint32_t cLen; + uint32_t cRem = len; + + do + { + m_dataFile.seekg(pages[cNext] * m_pageSize, std::ios_base::beg); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + m_dataFile.read(reinterpret_cast<char*>(m_buffer), m_pageSize); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + cLen = (cRem > m_pageSize) ? m_pageSize : cRem; + memcpy(ptr, m_buffer, cLen); + + ptr += cLen; + cRem -= cLen; + ++cNext; + } + while (cNext < cTotal); +} + +void DiskStorageManager::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + if (page == NewPage) + { + Entry* e = new Entry(); + e->m_length = len; + + const byte* ptr = data; + id_type cPage; + uint32_t cRem = len; + uint32_t cLen; + + while (cRem > 0) + { + if (! m_emptyPages.empty()) + { + cPage = m_emptyPages.top(); m_emptyPages.pop(); + } + else + { + cPage = m_nextPage; + ++m_nextPage; + } + + cLen = (cRem > m_pageSize) ? m_pageSize : cRem; + memcpy(m_buffer, ptr, cLen); + + m_dataFile.seekp(cPage * m_pageSize, std::ios_base::beg); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + m_dataFile.write(reinterpret_cast<const char*>(m_buffer), m_pageSize); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + ptr += cLen; + cRem -= cLen; + e->m_pages.push_back(cPage); + } + + page = e->m_pages[0]; + m_pageIndex.insert(std::pair<id_type, Entry*>(page, e)); + } + else + { + // find the entry. + std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page); + + // check if it exists. + if (it == m_pageIndex.end()) + throw InvalidPageException(page); + + Entry* oldEntry = (*it).second; + + m_pageIndex.erase(it); + + Entry* e = new Entry(); + e->m_length = len; + + const byte* ptr = data; + id_type cPage; + uint32_t cRem = len; + uint32_t cLen, cNext = 0; + + while (cRem > 0) + { + if (cNext < oldEntry->m_pages.size()) + { + cPage = oldEntry->m_pages[cNext]; + ++cNext; + } + else if (! m_emptyPages.empty()) + { + cPage = m_emptyPages.top(); m_emptyPages.pop(); + } + else + { + cPage = m_nextPage; + ++m_nextPage; + } + + cLen = (cRem > m_pageSize) ? m_pageSize : cRem; + memcpy(m_buffer, ptr, cLen); + + m_dataFile.seekp(cPage * m_pageSize, std::ios_base::beg); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + m_dataFile.write(reinterpret_cast<const char*>(m_buffer), m_pageSize); + if (m_dataFile.fail()) + throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file."); + + ptr += cLen; + cRem -= cLen; + e->m_pages.push_back(cPage); + } + + while (cNext < oldEntry->m_pages.size()) + { + m_emptyPages.push(oldEntry->m_pages[cNext]); + ++cNext; + } + + m_pageIndex.insert(std::pair<id_type, Entry*>(page, e)); + delete oldEntry; + } +} + +void DiskStorageManager::deleteByteArray(const id_type page) +{ + std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page); + + if (it == m_pageIndex.end()) + throw InvalidPageException(page); + + for (uint32_t cIndex = 0; cIndex < (*it).second->m_pages.size(); ++cIndex) + { + m_emptyPages.push((*it).second->m_pages[cIndex]); + } + + delete (*it).second; + m_pageIndex.erase(it); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/DiskStorageManager.h b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/DiskStorageManager.h new file mode 100644 index 000000000..178eb684e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/DiskStorageManager.h @@ -0,0 +1,58 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace StorageManager + { + class DiskStorageManager : public SpatialIndex::IStorageManager + { + public: + DiskStorageManager(Tools::PropertySet&); + virtual ~DiskStorageManager(); + + void flush(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + private: + class Entry + { + public: + uint32_t m_length; + std::vector<id_type> m_pages; + }; + + std::fstream m_dataFile; + std::fstream m_indexFile; + uint32_t m_pageSize; + id_type m_nextPage; + std::priority_queue<id_type, std::vector<id_type>, std::greater<id_type> > m_emptyPages; + std::map<id_type, Entry*> m_pageIndex; + + byte* m_buffer; + }; // DiskStorageManager + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Makefile.am new file mode 100644 index 000000000..430ab3dac --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/Makefile.am @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libstoragemanager.la +INCLUDES = -I../../include +libstoragemanager_la_SOURCES = Buffer.h Buffer.cc DiskStorageManager.cc MemoryStorageManager.cc RandomEvictionsBuffer.cc DiskStorageManager.h MemoryStorageManager.h RandomEvictionsBuffer.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/MemoryStorageManager.cc b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/MemoryStorageManager.cc new file mode 100644 index 000000000..24ef0e04b --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/MemoryStorageManager.cc @@ -0,0 +1,126 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <stdexcept> +#include <cstring> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "MemoryStorageManager.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnMemoryStorageManager(Tools::PropertySet& ps) +{ + IStorageManager* sm = new MemoryStorageManager(ps); + return sm; +} + +SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewMemoryStorageManager() +{ + Tools::PropertySet ps; + return returnMemoryStorageManager(ps); +} + +MemoryStorageManager::MemoryStorageManager(Tools::PropertySet& ps) +{ +} + +MemoryStorageManager::~MemoryStorageManager() +{ + for (std::vector<Entry*>::iterator it = m_buffer.begin(); it != m_buffer.end(); ++it) delete *it; +} + +void MemoryStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data) +{ + Entry* e; + try + { + e = m_buffer.at(page); + if (e == 0) throw InvalidPageException(page); + } + catch (std::out_of_range) + { + throw InvalidPageException(page); + } + + len = e->m_length; + *data = new byte[len]; + + memcpy(*data, e->m_pData, len); +} + +void MemoryStorageManager::storeByteArray(id_type& page, const uint32_t len, const byte* const data) +{ + if (page == NewPage) + { + Entry* e = new Entry(len, data); + + if (m_emptyPages.empty()) + { + m_buffer.push_back(e); + page = m_buffer.size() - 1; + } + else + { + page = m_emptyPages.top(); m_emptyPages.pop(); + m_buffer[page] = e; + } + } + else + { + Entry* e_old; + try + { + e_old = m_buffer.at(page); + if (e_old == 0) throw InvalidPageException(page); + } + catch (std::out_of_range) + { + throw InvalidPageException(page); + } + + Entry* e = new Entry(len, data); + + delete e_old; + m_buffer[page] = e; + } +} + +void MemoryStorageManager::deleteByteArray(const id_type page) +{ + Entry* e; + try + { + e = m_buffer.at(page); + if (e == 0) throw InvalidPageException(page); + } + catch (std::out_of_range) + { + throw InvalidPageException(page); + } + + m_buffer[page] = 0; + m_emptyPages.push(page); + + delete e; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/MemoryStorageManager.h b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/MemoryStorageManager.h new file mode 100644 index 000000000..61a224d80 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/MemoryStorageManager.h @@ -0,0 +1,61 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include <cstring> + +namespace SpatialIndex +{ + namespace StorageManager + { + class MemoryStorageManager : public SpatialIndex::IStorageManager + { + public: + MemoryStorageManager(Tools::PropertySet&); + + virtual ~MemoryStorageManager(); + + virtual void loadByteArray(const id_type page, uint32_t& len, byte** data); + virtual void storeByteArray(id_type& page, const uint32_t len, const byte* const data); + virtual void deleteByteArray(const id_type page); + + private: + class Entry + { + public: + byte* m_pData; + uint32_t m_length; + + Entry(uint32_t l, const byte* const d) : m_pData(0), m_length(l) + { + m_pData = new byte[m_length]; + memcpy(m_pData, d, m_length); + } + + ~Entry() { delete[] m_pData; } + }; // Entry + + std::vector<Entry*> m_buffer; + std::stack<id_type> m_emptyPages; + }; // MemoryStorageManager + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/RandomEvictionsBuffer.cc b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/RandomEvictionsBuffer.cc new file mode 100644 index 000000000..e0e22d296 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/RandomEvictionsBuffer.cc @@ -0,0 +1,94 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <time.h> +#include <stdlib.h> +#include <cmath> +#include "../../include/tools/rand48.h" + +#include "../spatialindex/SpatialIndexImpl.h" +#include "RandomEvictionsBuffer.h" + +using namespace SpatialIndex; +using namespace SpatialIndex::StorageManager; + +IBuffer* SpatialIndex::StorageManager::returnRandomEvictionsBuffer(IStorageManager& sm, Tools::PropertySet& ps) +{ + IBuffer* b = new RandomEvictionsBuffer(sm, ps); + return b; +} + +IBuffer* SpatialIndex::StorageManager::createNewRandomEvictionsBuffer(IStorageManager& sm, uint32_t capacity, bool bWriteThrough) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = capacity; + ps.setProperty("Capacity", var); + + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = bWriteThrough; + ps.setProperty("WriteThrough", var); + + return returnRandomEvictionsBuffer(sm, ps); +} + +RandomEvictionsBuffer::RandomEvictionsBuffer(IStorageManager& sm, Tools::PropertySet& ps) : Buffer(sm, ps) +{ + srand48(static_cast<uint32_t>(time(0))); +} + +RandomEvictionsBuffer::~RandomEvictionsBuffer() +{ +} + +void RandomEvictionsBuffer::addEntry(id_type page, Entry* e) +{ + assert(m_buffer.size() <= m_capacity); + + if (m_buffer.size() == m_capacity) removeEntry(); + assert(m_buffer.find(page) == m_buffer.end()); + m_buffer.insert(std::pair<id_type, Entry*>(page, e)); +} + +void RandomEvictionsBuffer::removeEntry() +{ + if (m_buffer.size() == 0) return; + + double random; + + random = drand48(); + + uint32_t entry = static_cast<uint32_t>(floor(((double) m_buffer.size()) * random)); + + std::map<id_type, Entry*>::iterator it = m_buffer.begin(); + for (uint32_t cIndex = 0; cIndex < entry; cIndex++) ++it; + + if ((*it).second->m_bDirty) + { + id_type page = (*it).first; + m_pStorageManager->storeByteArray(page, ((*it).second)->m_length, (const byte *) ((*it).second)->m_pData); + } + + delete (*it).second; + m_buffer.erase(it); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/RandomEvictionsBuffer.h b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/RandomEvictionsBuffer.h new file mode 100644 index 000000000..64f26681c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/RandomEvictionsBuffer.h @@ -0,0 +1,42 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Buffer.h" + +namespace SpatialIndex +{ + namespace StorageManager + { + class RandomEvictionsBuffer : public Buffer + { + public: + RandomEvictionsBuffer(IStorageManager&, Tools::PropertySet& ps); + // see Buffer.h for available properties. + + virtual ~RandomEvictionsBuffer(); + + virtual void addEntry(id_type page, Buffer::Entry* pEntry); + virtual void removeEntry(); + }; // RandomEvictionsBuffer + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/all-wcprops new file mode 100644 index 000000000..e62a9d87c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 55 +/spatialindex/!svn/ver/192/spatialindex/trunk/src/tools +END +Tools.cc +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/192/spatialindex/trunk/src/tools/Tools.cc +END +rand48.cc +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/69/spatialindex/trunk/src/tools/rand48.cc +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/99/spatialindex/trunk/src/tools/Makefile.am +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/dir-prop-base new file mode 100644 index 000000000..981994deb --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/dir-prop-base @@ -0,0 +1,11 @@ +K 10 +svn:ignore +V 48 +Makefile.in +geometry +tools +.libs +.deps +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/entries new file mode 100644 index 000000000..ff93e5df5 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/entries @@ -0,0 +1,130 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/tools +http://svn.gispython.org/spatialindex + + + +2010-10-14T13:18:23.380119Z +192 +mhadji +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Tools.cc +file + + + + +2011-08-01T00:42:34.413114Z +f618b02d67eb86196340c030c7d844ca +2010-10-14T13:18:23.380119Z +192 +mhadji + + + + + + + + + + + + + + + + + + + + + +32390 + +rand48.cc +file + + + + +2011-08-01T00:42:34.413114Z +8d4eb03c1b578802bf3484c9ca4ce755 +2008-02-26T16:15:43.620812Z +69 +hobu + + + + + + + + + + + + + + + + + + + + + +3560 + +Makefile.am +file + + + + +2011-08-01T00:42:34.413114Z +edc8140c6fff84fb52c4f6d9f3932bdc +2009-07-18T22:19:07.374702Z +99 +mhadji +has-props + + + + + + + + + + + + + + + + + + + + +183 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/prop-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/prop-base/Makefile.am.svn-base new file mode 100644 index 000000000..869ac71cf --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/prop-base/Makefile.am.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..eae038194 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libtools.la +INCLUDES = -I../../../include/tools +libtools_la_SOURCES = Tools.cc rand48.cc diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/Tools.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/Tools.cc.svn-base new file mode 100644 index 000000000..a8f4a970e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/Tools.cc.svn-base @@ -0,0 +1,1365 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <time.h> +#include <limits> +#include "../../include/tools/Tools.h" +#include "../../include/tools/rand48.h" + +#include <cstring> + +Tools::IndexOutOfBoundsException::IndexOutOfBoundsException(size_t i) +{ + std::ostringstream s; + s << "Invalid index " << i; + m_error = s.str(); +} + +std::string Tools::IndexOutOfBoundsException::what() +{ + return "IndexOutOfBoundsException: " + m_error; +} + +Tools::IllegalArgumentException::IllegalArgumentException(std::string s) : m_error(s) +{ +} + +std::string Tools::IllegalArgumentException::what() +{ + return "IllegalArgumentException: " + m_error; +} + +Tools::IllegalStateException::IllegalStateException(std::string s) : m_error(s) +{ +} + +std::string Tools::IllegalStateException::what() +{ + return "IllegalStateException: " + m_error; +} + +Tools::EndOfStreamException::EndOfStreamException(std::string s) : m_error(s) +{ +} + +std::string Tools::EndOfStreamException::what() +{ + return "EndOfStreamException: " + m_error; +} + +Tools::ResourceLockedException::ResourceLockedException(std::string s) : m_error(s) +{ +} + +std::string Tools::ResourceLockedException::what() +{ + return "ResourceLockedException: " + m_error; +} + +Tools::NotSupportedException::NotSupportedException(std::string s) : m_error(s) +{ +} + +std::string Tools::NotSupportedException::what() +{ + return "NotSupportedException: " + m_error; +} + +Tools::Variant::Variant() : m_varType(VT_EMPTY) +{ +} + +Tools::PropertySet::PropertySet(const byte* data) +{ +#ifdef HAVE_PTHREAD_H + // pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + loadFromByteArray(data); +} + +Tools::PropertySet::~PropertySet() +{ +#ifdef HAVE_PTHREAD_H + // pthread_rwlock_destroy(&m_rwLock); +#endif +} + +Tools::PropertySet::PropertySet() +{ +#ifdef HAVE_PTHREAD_H + // pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif +} +void Tools::PropertySet::loadFromByteArray(const byte* ptr) +{ + m_propertySet.clear(); + + uint32_t numberOfProperties; + memcpy(&numberOfProperties, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + Variant v; + + for (uint32_t cIndex = 0; cIndex < numberOfProperties; ++cIndex) + { + std::string s(reinterpret_cast<const char*>(ptr)); + ptr += s.size() + 1; + memcpy(&(v.m_varType), ptr, sizeof(VariantType)); + ptr += sizeof(VariantType); + + switch (v.m_varType) + { + case VT_SHORT: + int16_t s; + memcpy(&s, ptr, sizeof(int16_t)); + ptr += sizeof(int16_t); + v.m_val.iVal = s; + break; + case VT_LONG: + int32_t l; + memcpy(&l, ptr, sizeof(int32_t)); + ptr += sizeof(int32_t); + v.m_val.lVal = l; + break; + case VT_LONGLONG: + int64_t ll; + memcpy(&ll, ptr, sizeof(int64_t)); + ptr += sizeof(int64_t); + v.m_val.llVal = ll; + break; + case VT_BYTE: + byte b; + memcpy(&b, ptr, sizeof(byte)); + ptr += sizeof(byte); + v.m_val.bVal = b; + break; + case VT_FLOAT: + float f; + memcpy(&f, ptr, sizeof(float)); + ptr += sizeof(float); + v.m_val.fltVal = f; + break; + case VT_DOUBLE: + double d; + memcpy(&d, ptr, sizeof(double)); + ptr += sizeof(double); + v.m_val.dblVal = d; + break; + case VT_CHAR: + char c; + memcpy(&c, ptr, sizeof(char)); + ptr += sizeof(char); + v.m_val.cVal = c; + break; + case VT_USHORT: + uint16_t us; + memcpy(&us, ptr, sizeof(uint16_t)); + ptr += sizeof(uint16_t); + v.m_val.uiVal = us; + break; + case VT_ULONG: + uint32_t ul; + memcpy(&ul, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + v.m_val.ulVal = ul; + break; + case VT_ULONGLONG: + uint64_t ull; + memcpy(&ull, ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + v.m_val.ullVal = ull; + break; + case VT_BOOL: + byte bl; + memcpy(&bl, ptr, sizeof(byte)); + ptr += sizeof(byte); + v.m_val.blVal = (bl != 0); + break; + default: + throw IllegalStateException( + "Tools::PropertySet::PropertySet: Deserialization problem." + ); + } + + m_propertySet.insert(std::pair<std::string, Variant>(s, v)); + } +} + +uint32_t Tools::PropertySet::getByteArraySize() +{ + uint32_t size = sizeof(uint32_t); + std::map<std::string, Variant>::iterator it; + + for (it = m_propertySet.begin(); it != m_propertySet.end(); ++it) + { + switch ((*it).second.m_varType) + { + case VT_SHORT: + size += sizeof(int16_t); + break; + case VT_LONG: + size += sizeof(int32_t); + break; + case VT_LONGLONG: + size += sizeof(int64_t); + break; + case VT_BYTE: + size += sizeof(byte); + break; + case VT_FLOAT: + size += sizeof(float); + break; + case VT_DOUBLE: + size += sizeof(double); + break; + case VT_CHAR: + size += sizeof(char); + break; + case VT_USHORT: + size += sizeof(uint16_t); + break; + case VT_ULONG: + size += sizeof(uint32_t); + break; + case VT_ULONGLONG: + size += sizeof(uint64_t); + break; + case VT_BOOL: + size += sizeof(byte); + break; + default: + throw NotSupportedException( + "Tools::PropertySet::getSize: Unknown type." + ); + } + size += static_cast<uint32_t>((*it).first.size()) + 1 + sizeof(VariantType); + } + + return size; +} + +void Tools::PropertySet::storeToByteArray(byte** data, uint32_t& length) +{ + length = getByteArraySize(); + *data = new byte[length]; + byte* ptr = *data; + + uint32_t numberOfProperties = static_cast<uint32_t>(m_propertySet.size()); + memcpy(ptr, &numberOfProperties, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + std::map<std::string, Variant>::iterator it; + + for (it = m_propertySet.begin(); it != m_propertySet.end(); ++it) + { + size_t strSize = (*it).first.size(); + memcpy(ptr, (*it).first.c_str(), strSize); + ptr += strSize; + *ptr = 0; + ++ptr; + + memcpy(ptr, &((*it).second.m_varType), sizeof(VariantType)); + ptr += sizeof(VariantType); + + switch ((*it).second.m_varType) + { + case VT_SHORT: + memcpy(ptr, &((*it).second.m_val.iVal), sizeof(int16_t)); + ptr += sizeof(int16_t); + break; + case VT_LONG: + memcpy(ptr, &((*it).second.m_val.lVal), sizeof(int32_t)); + ptr += sizeof(int32_t); + break; + case VT_LONGLONG: + memcpy(ptr, &((*it).second.m_val.llVal), sizeof(int64_t)); + ptr += sizeof(int64_t); + break; + case VT_BYTE: + memcpy(ptr, &((*it).second.m_val.bVal), sizeof(byte)); + ptr += sizeof(byte); + break; + case VT_FLOAT: + memcpy(ptr, &((*it).second.m_val.fltVal), sizeof(float)); + ptr += sizeof(float); + break; + case VT_DOUBLE: + memcpy(ptr, &((*it).second.m_val.dblVal), sizeof(double)); + ptr += sizeof(double); + break; + case VT_CHAR: + memcpy(ptr, &((*it).second.m_val.cVal), sizeof(char)); + ptr += sizeof(char); + break; + case VT_USHORT: + memcpy(ptr, &((*it).second.m_val.uiVal), sizeof(uint16_t)); + ptr += sizeof(uint16_t); + break; + case VT_ULONG: + memcpy(ptr, &((*it).second.m_val.ulVal), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + break; + case VT_ULONGLONG: + memcpy(ptr, &((*it).second.m_val.ullVal), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + break; + case VT_BOOL: + byte bl; + bl = (*it).second.m_val.blVal; + memcpy(ptr, &bl, sizeof(byte)); + ptr += sizeof(byte); + break; + default: + throw NotSupportedException( + "Tools::PropertySet::getData: Cannot serialize a variant of this type." + ); + } + } + + assert(ptr == (*data) + length); +} + +Tools::Variant Tools::PropertySet::getProperty(std::string property) +{ +// #ifdef HAVE_PTHREAD_H +// Tools::ExclusiveLock lock(&m_rwLock); +// #else +// if (m_rwLock == false) m_rwLock = true; +// else throw Tools::IllegalStateException("getProperty: cannot acquire an shared lock"); +// #endif + + try + { + std::map<std::string, Variant>::iterator it = m_propertySet.find(property); + + if (it != m_propertySet.end()) return (*it).second; + else return Variant(); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void Tools::PropertySet::setProperty(std::string property, Variant& v) +{ +#ifdef HAVE_PTHREAD_H + // Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::EndOfStreamException("setProperty: cannot acquire an exclusive lock"); +#endif + + try + { + std::pair<std::map<std::string, Variant>::iterator, bool> ret; + std::map<std::string, Variant>::iterator it; + + ret = m_propertySet.insert(std::pair<std::string, Variant>(property, v)); + + // If we weren't able to insert because it is already in the map + // update our existing value + if (ret.second == false) ret.first->second = v; + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void Tools::PropertySet::removeProperty(std::string property) +{ +#ifdef HAVE_PTHREAD_H + // Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::EndOfStreamException("setProperty: cannot acquire an exclusive lock"); +#endif + + try + { + std::map<std::string, Variant>::iterator it = m_propertySet.find(property); + if (it != m_propertySet.end()) m_propertySet.erase(it); + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +Tools::Interval::Interval() : m_type(IT_RIGHTOPEN), m_low(0.0), m_high(0.0) +{ +} + +Tools::Interval::Interval(IntervalType t, double l, double h) : m_type(t), m_low(l), m_high(h) +{ + assert(l < h); +} + +Tools::Interval::Interval(double l, double h) : m_type(IT_RIGHTOPEN), m_low(l), m_high(h) +{ + assert(l < h); +} + +Tools::Interval::Interval(const Interval& iv) +{ + m_low = iv.m_low; + m_high = iv.m_high; + m_type = iv.m_type; +} + +Tools::IInterval& Tools::Interval::operator=(const Tools::IInterval& iv) +{ + if (this != &iv) + { + m_low = iv.getLowerBound(); + m_high = iv.getUpperBound(); + m_type = iv.getIntervalType(); + } + + return *this; +} + +bool Tools::Interval::operator==(const Interval& iv) const +{ + if ( + m_type == iv.m_type && + m_low >= iv.m_low - std::numeric_limits<double>::epsilon() && + m_low <= iv.m_low + std::numeric_limits<double>::epsilon() && + m_high >= iv.m_high - std::numeric_limits<double>::epsilon() && + m_high <= iv.m_high + std::numeric_limits<double>::epsilon()) + return true; + + return false; +} + +bool Tools::Interval::operator!=(const Interval& iv) const +{ + return ! (*this == iv); +} + +double Tools::Interval::getLowerBound() const +{ + return m_low; +} + +double Tools::Interval::getUpperBound() const +{ + return m_high; +} + +void Tools::Interval::setBounds(double l, double h) +{ + assert(l <= h); + + m_low = l; + m_high = h; +} + +bool Tools::Interval::intersectsInterval(const IInterval& i) const +{ + return intersectsInterval(i.getIntervalType(), i.getLowerBound(), i.getUpperBound()); +} + +bool Tools::Interval::intersectsInterval(IntervalType type, const double low, const double high) const +{ + if (m_high < m_low) + throw IllegalStateException( + "Tools::Interval::intersectsInterval: high boundary is smaller than low boundary." + ); + + if (m_low > high || m_high < low) return false; + if ((m_low > low && m_low < high) || (m_high > low && m_high < high)) return true; + + switch (m_type) + { + case IT_CLOSED: + if (m_low == high) + { + if (type == IT_CLOSED || type == IT_LEFTOPEN) return true; + else return false; + } + else if (m_high == low) + { + if (type == IT_CLOSED || type == IT_RIGHTOPEN) return true; + else return false; + } + break; + case IT_OPEN: + if (m_low == high || m_high == low) return false; + break; + case IT_RIGHTOPEN: + if (m_low == high) + { + if (type == IT_CLOSED || type == IT_LEFTOPEN) return true; + else return false; + } + else if (m_high == low) + { + return false; + } + break; + case IT_LEFTOPEN: + if (m_low == high) + { + return false; + } + else if (m_high == low) + { + if (type == IT_CLOSED || type == IT_RIGHTOPEN) return true; + else return false; + } + break; + } + + return true; +} + +bool Tools::Interval::containsInterval(const IInterval& i) const +{ + if (m_high < m_low) + throw IllegalStateException( + "Tools::Interval::containsInterval: high boundary is smaller than low boundary." + ); + + double low = i.getLowerBound(); + double high = i.getUpperBound(); + IntervalType type = i.getIntervalType(); + + if (m_low < low && m_high > high) return true; + if (m_low > low || m_high < high) return false; + + switch (m_type) + { + case IT_CLOSED: + break; + case IT_OPEN: + if ((m_low == low && m_high == high && type != IT_OPEN) || + (m_low == low && (type == IT_CLOSED || type == IT_RIGHTOPEN)) || + (m_high == high && ( type == IT_CLOSED || type == IT_LEFTOPEN))) + return false; + break; + case IT_RIGHTOPEN: + if (m_high == high && (type == IT_CLOSED || type == IT_LEFTOPEN)) + return false; + break; + case IT_LEFTOPEN: + if (m_low == low && (type == IT_CLOSED || type == IT_RIGHTOPEN)) + return false; + break; + } + + return true; +} + +Tools::IntervalType Tools::Interval::getIntervalType() const +{ + return m_type; +} + +Tools::Random::Random() +{ + m_pBuffer = 0; + initDrand(static_cast<uint32_t>(time(0)), 0xD31A); +} + +Tools::Random::Random(uint32_t seed, uint16_t xsubi0) +{ + m_pBuffer = 0; + initDrand(seed, xsubi0); +} + +Tools::Random::~Random() +{ + delete[] m_pBuffer; +} + +void Tools::Random::initDrand(uint32_t seed, uint16_t xsubi0) +{ + m_pBuffer = new uint16_t[3]; + m_pBuffer[0] = static_cast<uint16_t>(xsubi0); + uint32_t mask = 0xFFFF; + m_pBuffer[1] = static_cast<uint16_t>(seed & mask); + mask = mask << 16; + m_pBuffer[2] = static_cast<uint16_t>((seed & mask) >> 16); + +#ifdef BUILD_OS_CYGWIN + srand48(*(reinterpret_cast<uint32_t*>(m_pBuffer))); + // BUG: There is a bug in cygwin gcc 3.4.4. srand48 needs to be called + // even if we are using the functions that take the seed as a parameter. + // This does not affect random number generation, which still happens + // using the seed provided as a parameter and not the one provided to srand48 :-S +#endif +} + +int32_t Tools::Random::nextUniformLong() +{ + return jrand48(m_pBuffer); +} + +uint32_t Tools::Random::nextUniformUnsignedLong() +{ + return static_cast<uint32_t>(nextUniformLong()); +} + +int32_t Tools::Random::nextUniformLong(int32_t low, int32_t high) +{ + return low + static_cast<int32_t>((high - low) * nextUniformDouble()); +} + +uint32_t Tools::Random::nextUniformUnsignedLong(uint32_t low, uint32_t high) +{ + return low + static_cast<uint32_t>((high - low) * nextUniformDouble()); +} + +int64_t Tools::Random::nextUniformLongLong() +{ + return static_cast<int64_t>(nextUniformUnsignedLongLong()); +} + +uint64_t Tools::Random::nextUniformUnsignedLongLong() +{ + uint64_t lh = static_cast<uint64_t>(nextUniformLong()); + uint64_t ll = static_cast<uint64_t>(nextUniformLong()); + uint64_t ret = (lh << 32) | ll; + return ret; +} + +int64_t Tools::Random::nextUniformLongLong(int64_t low, int64_t high) +{ + return low + static_cast<int64_t>((high - low) * nextUniformDouble()); +} + +uint64_t Tools::Random::nextUniformUnsignedLongLong(uint64_t low, uint64_t high) +{ + return low + static_cast<uint64_t>((high - low) * nextUniformDouble()); +} + +int16_t Tools::Random::nextUniformShort() +{ + return static_cast<int16_t>(nextUniformUnsignedShort()); +} + +uint16_t Tools::Random::nextUniformUnsignedShort() +{ + return nextUniformUnsignedLong() >> 16; + // retain the high order bits. +} + +double Tools::Random::nextUniformDouble() +{ + uint16_t* xsubi = reinterpret_cast<uint16_t*>(m_pBuffer); + return erand48(xsubi); +} + +double Tools::Random::nextUniformDouble(double low, double high) +{ + return (high - low) * nextUniformDouble() + low; +} + +bool Tools::Random::flipCoin() +{ + if (nextUniformDouble() < 0.5) return true; + return false; +} + +#if HAVE_PTHREAD_H +Tools::SharedLock::SharedLock(pthread_rwlock_t* pLock) + : m_pLock(pLock) +{ + pthread_rwlock_rdlock(m_pLock); +} + +Tools::SharedLock::~SharedLock() +{ + pthread_rwlock_unlock(m_pLock); +} + +Tools::ExclusiveLock::ExclusiveLock(pthread_rwlock_t* pLock) + : m_pLock(pLock) +{ + pthread_rwlock_wrlock(m_pLock); +} + +Tools::ExclusiveLock::~ExclusiveLock() +{ + pthread_rwlock_unlock(m_pLock); +} +#endif + +std::ostream& Tools::operator<<(std::ostream& os, const Tools::PropertySet& p) +{ + std::map<std::string, Variant>::const_iterator it; + + for (it = p.m_propertySet.begin(); it != p.m_propertySet.end(); ++it) + { + if (it != p.m_propertySet.begin()) os << ", "; + + switch ((*it).second.m_varType) + { + case VT_LONG: + os << (*it).first << ": " << (*it).second.m_val.lVal; + break; + case VT_LONGLONG: + os << (*it).first << ": " << (*it).second.m_val.llVal; + break; + case VT_BYTE: + os << (*it).first << ": " << (*it).second.m_val.bVal; + break; + case VT_SHORT: + os << (*it).first << ": " << (*it).second.m_val.iVal; + break; + case VT_FLOAT: + os << (*it).first << ": " << (*it).second.m_val.fltVal; + break; + case VT_DOUBLE: + os << (*it).first << ": " << (*it).second.m_val.dblVal; + break; + case VT_CHAR: + os << (*it).first << ": " << (*it).second.m_val.cVal; + break; + case VT_USHORT: + os << (*it).first << ": " << (*it).second.m_val.uiVal; + break; + case VT_ULONG: + os << (*it).first << ": " << (*it).second.m_val.ulVal; + break; + case VT_ULONGLONG: + os << (*it).first << ": " << (*it).second.m_val.ullVal; + break; + case VT_BOOL: + os << (*it).first << ": " << (*it).second.m_val.blVal; + break; + case VT_PCHAR: + os << (*it).first << ": " << (*it).second.m_val.pcVal; + break; + case VT_PVOID: + os << (*it).first << ": ?"; + break; + case VT_EMPTY: + os << (*it).first << ": empty"; + break; + default: + os << (*it).first << ": unknown"; + } + } + + return os; +} + +std::ostream& Tools::operator<<(std::ostream& os, const Tools::Interval& iv) +{ + os << iv.m_type << " " << iv.m_low << " " << iv.m_high; + return os; +} + +// +// BufferedFile +// +Tools::BufferedFile::BufferedFile(uint32_t u32BufferSize) +: m_buffer(new char[u32BufferSize]), m_u32BufferSize(u32BufferSize), m_bEOF(true) +{ +} + +Tools::BufferedFile::~BufferedFile() +{ + m_file.close(); + delete[] m_buffer; +} + +void Tools::BufferedFile::close() +{ + m_file.close(); +} + +bool Tools::BufferedFile::eof() +{ + return m_bEOF; +} + +// +// BufferedFileReader +// +Tools::BufferedFileReader::BufferedFileReader() +{ +} + +Tools::BufferedFileReader::BufferedFileReader(const std::string& sFileName, uint32_t u32BufferSize) +: BufferedFile(u32BufferSize) +{ + open(sFileName); +} + +void Tools::BufferedFileReader::open(const std::string& sFileName) +{ + m_bEOF = false; + m_file.close(); m_file.clear(); + + + m_file.open(sFileName.c_str(), std::ios_base::in | std::ios_base::binary); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileReader::BufferedFileReader: Cannot open file."); + + m_file.rdbuf()->pubsetbuf(m_buffer, m_u32BufferSize); +} + +Tools::BufferedFileReader::~BufferedFileReader() +{ +} + +void Tools::BufferedFileReader::rewind() +{ + m_file.clear(); + m_file.seekg(0, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileReader::rewind: seek failed."); + + m_bEOF = false; +} + +void Tools::BufferedFileReader::seek(std::fstream::off_type offset) +{ + m_bEOF = false; + m_file.clear(); + m_file.seekg(offset, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileReader::seek: seek failed."); +} + +uint8_t Tools::BufferedFileReader::readUInt8() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint8_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint8_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +uint16_t Tools::BufferedFileReader::readUInt16() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint16_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint16_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +uint32_t Tools::BufferedFileReader::readUInt32() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint32_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint32_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +uint64_t Tools::BufferedFileReader::readUInt64() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint64_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint64_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +float Tools::BufferedFileReader::readFloat() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + float ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(float)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +double Tools::BufferedFileReader::readDouble() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + double ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(double)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +bool Tools::BufferedFileReader::readBoolean() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + bool ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(bool)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +std::string Tools::BufferedFileReader::readString() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint32_t len; + m_file.read(reinterpret_cast<char*>(&len), sizeof(uint32_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + + std::string::value_type* buf = new std::string::value_type[len]; + m_file.read(reinterpret_cast<char*>(buf), len * sizeof(std::string::value_type)); + if (! m_file.good()) + { + delete[] buf; + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + + std::string ret(buf, len); + delete[] buf; + + return ret; +} + +void Tools::BufferedFileReader::readBytes(uint32_t u32Len, byte** pData) +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + *pData = new byte[u32Len]; + m_file.read(reinterpret_cast<char*>(*pData), u32Len); + if (! m_file.good()) + { + delete[] *pData; + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } +} + +// +// BufferedFileWriter +// +Tools::BufferedFileWriter::BufferedFileWriter() +{ + open(""); +} + +Tools::BufferedFileWriter::BufferedFileWriter(const std::string& sFileName, FileMode mode, uint32_t u32BufferSize) +: BufferedFile(u32BufferSize) +{ + open(sFileName, mode); +} + +Tools::BufferedFileWriter::~BufferedFileWriter() +{ + m_file.flush(); +} + +void Tools::BufferedFileWriter::open(const std::string& sFileName, FileMode mode) +{ + m_bEOF = false; + m_file.close(); m_file.clear(); + + if (mode == CREATE) + { + m_file.open(sFileName.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file."); + } + else if (mode == APPEND) + { + // Idiotic fstream::open truncates an existing file anyway, if it is only opened + // for output (no ios_base::in flag)!! On the other hand, if a file does not exist + // and the ios_base::in flag is specified, then the open fails!! + + m_file.open(sFileName.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (! m_file.good()) + { + m_file.clear(); + m_file.open(sFileName.c_str(), std::ios_base::out | std::ios_base::binary); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file."); + } + else + { + m_file.seekp(0, std::ios_base::end); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file."); + } + } + else + throw Tools::IllegalArgumentException("Tools::BufferedFileWriter::open: Unknown mode."); +} + +void Tools::BufferedFileWriter::rewind() +{ + m_bEOF = false; + m_file.clear(); + m_file.seekp(0, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::rewind: seek failed."); +} + +void Tools::BufferedFileWriter::seek(std::fstream::off_type offset) +{ + m_bEOF = false; + m_file.clear(); + m_file.seekp(offset, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::seek: seek failed."); +} + +void Tools::BufferedFileWriter::write(uint8_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint8_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint16_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint16_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint32_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint32_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint64_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint64_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(float i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(float)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(double i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(double)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(bool b) +{ + m_file.write(reinterpret_cast<const char*>(&b), sizeof(bool)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(const std::string& s) +{ + uint32_t len = static_cast<uint32_t>(s.size()); + m_file.write(reinterpret_cast<const char*>(&len), sizeof(uint32_t)); + if (! m_file.good()) throw std::ios_base::failure(""); + m_file.write(reinterpret_cast<const char*>(s.c_str()), len * sizeof(std::string::value_type)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint32_t u32Len, byte* pData) +{ + m_file.write(reinterpret_cast<const char*>(pData), u32Len); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +// +// TemporaryFile +// +Tools::TemporaryFile::TemporaryFile() +{ + +#ifdef _MSC_VER + +#ifndef L_tmpnam_s +// MSVC 2003 doesn't have tmpnam_s, so we'll have to use the old functions + + char* tmpName = NULL; + tmpName = tmpnam( NULL ); + + if (tmpName == NULL) + throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name."); + +#else + char tmpName[L_tmpnam_s]; + errno_t err = tmpnam_s(tmpName, L_tmpnam_s); + if (err) + throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name."); + +#endif + if (tmpName[0] == '\\') + m_sFile = std::string(tmpName + 1); + else + m_sFile = std::string(tmpName); + +#else + char tmpName[7] = "XXXXXX"; + if (mktemp(tmpName) == 0) + throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name."); + m_sFile = tmpName; +#endif + + m_pFile = new Tools::BufferedFileWriter(m_sFile, Tools::CREATE); +} + +Tools::TemporaryFile::~TemporaryFile() +{ + delete m_pFile; + +#ifdef _MSC_VER + _unlink(m_sFile.c_str()); +#else + std::remove(m_sFile.c_str()); +#endif +} + +void Tools::TemporaryFile::rewindForReading() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br != 0) + m_pFile->rewind(); + else + { + delete m_pFile; + m_pFile = new Tools::BufferedFileReader(m_sFile); + } +} + +void Tools::TemporaryFile::rewindForWriting() +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw != 0) + m_pFile->rewind(); + else + { + delete m_pFile; + m_pFile = new Tools::BufferedFileWriter(m_sFile); + } +} + +bool Tools::TemporaryFile::eof() +{ + return m_pFile->eof(); +} + +std::string Tools::TemporaryFile::getFileName() const +{ + return m_sFile; +} + +uint8_t Tools::TemporaryFile::readUInt8() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt8: file not open for reading."); + + return br->readUInt8(); +} + +uint16_t Tools::TemporaryFile::readUInt16() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt16: file not open for reading."); + + return br->readUInt16(); +} + +uint32_t Tools::TemporaryFile::readUInt32() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt32: file not open for reading."); + + return br->readUInt32(); +} + +uint64_t Tools::TemporaryFile::readUInt64() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt64: file not open for reading."); + + return br->readUInt64(); +} + +float Tools::TemporaryFile::readFloat() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readFloat: file not open for reading."); + + return br->readFloat(); +} + +double Tools::TemporaryFile::readDouble() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readDouble: file not open for reading."); + + return br->readDouble(); +} + +std::string Tools::TemporaryFile::readString() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readString: file not open for reading."); + + return br->readString(); +} + +void Tools::TemporaryFile::readBytes(uint32_t u32Len, byte** pData) +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readString: file not open for reading."); + + return br->readBytes(u32Len, pData); +} + +void Tools::TemporaryFile::write(uint8_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(uint16_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(uint32_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(uint64_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(float i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(double i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(const std::string& s) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(s); +} + +void Tools::TemporaryFile::write(uint32_t u32Len, byte* pData) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(u32Len, pData); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/rand48.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/rand48.cc.svn-base new file mode 100644 index 000000000..cc406019d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/.svn/text-base/rand48.cc.svn-base @@ -0,0 +1,145 @@ +/* +* Copyright (c) 1993 Martin Birgmeier +* All rights reserved. +* +* You may redistribute unmodified or modified versions of this source +* code provided that the above copyright notice and this and the +* following conditions are retained. +* +* This software is provided ``as is'', and comes with no warranties +* of any kind. I shall in no event be liable for anything that happens +* to anyone/anything when using this software. +*/ + +#include <math.h> +#include <stdlib.h> + +#define RAND48_SEED_0 (0x330e) +#define RAND48_SEED_1 (0xabcd) +#define RAND48_SEED_2 (0x1234) +#define RAND48_MULT_0 (0xe66d) +#define RAND48_MULT_1 (0xdeec) +#define RAND48_MULT_2 (0x0005) +#define RAND48_ADD (0x000b) + + + /* Internal function to compute next state of the generator. */ +static void _dorand48(unsigned short[3]); + +/* Unfortunately, 3 __globals, which the exported functions must access */ +unsigned short __rand48_Seed[3] = { + RAND48_SEED_0, + RAND48_SEED_1, + RAND48_SEED_2 +}; +unsigned short __rand48_Mult[3] = { + RAND48_MULT_0, + RAND48_MULT_1, + RAND48_MULT_2 +}; +unsigned short __rand48_Add = RAND48_ADD; + +/* Internal function to compute next state of the generator. */ + static void +_dorand48(unsigned short xseed[3]) +{ + unsigned long accu; + unsigned short temp[2]; + + accu = (unsigned long) __rand48_Mult[0] * (unsigned long) xseed[0] + + (unsigned long) __rand48_Add; + temp[0] = (unsigned short) accu; /* lower 16 bits */ + accu >>= sizeof(unsigned short) * 8; + accu += (unsigned long) __rand48_Mult[0] * (unsigned long) xseed[1] + + (unsigned long) __rand48_Mult[1] * (unsigned long) xseed[0]; + temp[1] = (unsigned short) accu; /* middle 16 bits */ + accu >>= sizeof(unsigned short) * 8; + accu += __rand48_Mult[0] * xseed[2] + __rand48_Mult[1] * xseed[1] + + __rand48_Mult[2] * xseed[0]; + xseed[0] = temp[0]; + xseed[1] = temp[1]; + xseed[2] = (unsigned short) accu; +} + + extern void +srand48(long seed) +{ + __rand48_Seed[0] = RAND48_SEED_0; + __rand48_Seed[1] = (unsigned short) seed; + __rand48_Seed[2] = (unsigned short) (seed >> 16); + __rand48_Mult[0] = RAND48_MULT_0; + __rand48_Mult[1] = RAND48_MULT_1; + __rand48_Mult[2] = RAND48_MULT_2; + __rand48_Add = RAND48_ADD; +} + + extern unsigned short * +seed48(unsigned short xseed[3]) +{ + static unsigned short sseed[3]; + + sseed[0] = __rand48_Seed[0]; + sseed[1] = __rand48_Seed[1]; + sseed[2] = __rand48_Seed[2]; + __rand48_Seed[0] = xseed[0]; + __rand48_Seed[1] = xseed[1]; + __rand48_Seed[2] = xseed[2]; + __rand48_Mult[0] = RAND48_MULT_0; + __rand48_Mult[1] = RAND48_MULT_1; + __rand48_Mult[2] = RAND48_MULT_2; + __rand48_Add = RAND48_ADD; + return sseed; +} + + extern long +nrand48(unsigned short xseed[3]) +{ + _dorand48(xseed); + return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1); +} + extern long +mrand48(void) +{ + _dorand48(__rand48_Seed); + return ((long) __rand48_Seed[2] << 16) + (long) __rand48_Seed[1]; +} + + extern long +lrand48(void) +{ + _dorand48(__rand48_Seed); + return ((long) __rand48_Seed[2] << 15) + ((long) __rand48_Seed[1] >> 1); +} + + extern void +lcong48(unsigned short p[7]) +{ + __rand48_Seed[0] = p[0]; + __rand48_Seed[1] = p[1]; + __rand48_Seed[2] = p[2]; + __rand48_Mult[0] = p[3]; + __rand48_Mult[1] = p[4]; + __rand48_Mult[2] = p[5]; + __rand48_Add = p[6]; +} + extern long +jrand48(unsigned short xseed[3]) +{ + _dorand48(xseed); + return ((long) xseed[2] << 16) + (long) xseed[1]; +} + + extern double +erand48(unsigned short xseed[3]) +{ + _dorand48(xseed); + return ldexp((double) xseed[0], -48) + + ldexp((double) xseed[1], -32) + + ldexp((double) xseed[2], -16); +} + + extern double +drand48(void) +{ + return erand48(__rand48_Seed); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/tools/Makefile.am new file mode 100755 index 000000000..eae038194 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/Makefile.am @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libtools.la +INCLUDES = -I../../../include/tools +libtools_la_SOURCES = Tools.cc rand48.cc diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/Tools.cc b/sci-libs/libspatialindex/svn/trunk/src/tools/Tools.cc new file mode 100644 index 000000000..a8f4a970e --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/Tools.cc @@ -0,0 +1,1365 @@ +// Spatial Index Library +// +// Copyright (C) 2004 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <time.h> +#include <limits> +#include "../../include/tools/Tools.h" +#include "../../include/tools/rand48.h" + +#include <cstring> + +Tools::IndexOutOfBoundsException::IndexOutOfBoundsException(size_t i) +{ + std::ostringstream s; + s << "Invalid index " << i; + m_error = s.str(); +} + +std::string Tools::IndexOutOfBoundsException::what() +{ + return "IndexOutOfBoundsException: " + m_error; +} + +Tools::IllegalArgumentException::IllegalArgumentException(std::string s) : m_error(s) +{ +} + +std::string Tools::IllegalArgumentException::what() +{ + return "IllegalArgumentException: " + m_error; +} + +Tools::IllegalStateException::IllegalStateException(std::string s) : m_error(s) +{ +} + +std::string Tools::IllegalStateException::what() +{ + return "IllegalStateException: " + m_error; +} + +Tools::EndOfStreamException::EndOfStreamException(std::string s) : m_error(s) +{ +} + +std::string Tools::EndOfStreamException::what() +{ + return "EndOfStreamException: " + m_error; +} + +Tools::ResourceLockedException::ResourceLockedException(std::string s) : m_error(s) +{ +} + +std::string Tools::ResourceLockedException::what() +{ + return "ResourceLockedException: " + m_error; +} + +Tools::NotSupportedException::NotSupportedException(std::string s) : m_error(s) +{ +} + +std::string Tools::NotSupportedException::what() +{ + return "NotSupportedException: " + m_error; +} + +Tools::Variant::Variant() : m_varType(VT_EMPTY) +{ +} + +Tools::PropertySet::PropertySet(const byte* data) +{ +#ifdef HAVE_PTHREAD_H + // pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + loadFromByteArray(data); +} + +Tools::PropertySet::~PropertySet() +{ +#ifdef HAVE_PTHREAD_H + // pthread_rwlock_destroy(&m_rwLock); +#endif +} + +Tools::PropertySet::PropertySet() +{ +#ifdef HAVE_PTHREAD_H + // pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif +} +void Tools::PropertySet::loadFromByteArray(const byte* ptr) +{ + m_propertySet.clear(); + + uint32_t numberOfProperties; + memcpy(&numberOfProperties, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + Variant v; + + for (uint32_t cIndex = 0; cIndex < numberOfProperties; ++cIndex) + { + std::string s(reinterpret_cast<const char*>(ptr)); + ptr += s.size() + 1; + memcpy(&(v.m_varType), ptr, sizeof(VariantType)); + ptr += sizeof(VariantType); + + switch (v.m_varType) + { + case VT_SHORT: + int16_t s; + memcpy(&s, ptr, sizeof(int16_t)); + ptr += sizeof(int16_t); + v.m_val.iVal = s; + break; + case VT_LONG: + int32_t l; + memcpy(&l, ptr, sizeof(int32_t)); + ptr += sizeof(int32_t); + v.m_val.lVal = l; + break; + case VT_LONGLONG: + int64_t ll; + memcpy(&ll, ptr, sizeof(int64_t)); + ptr += sizeof(int64_t); + v.m_val.llVal = ll; + break; + case VT_BYTE: + byte b; + memcpy(&b, ptr, sizeof(byte)); + ptr += sizeof(byte); + v.m_val.bVal = b; + break; + case VT_FLOAT: + float f; + memcpy(&f, ptr, sizeof(float)); + ptr += sizeof(float); + v.m_val.fltVal = f; + break; + case VT_DOUBLE: + double d; + memcpy(&d, ptr, sizeof(double)); + ptr += sizeof(double); + v.m_val.dblVal = d; + break; + case VT_CHAR: + char c; + memcpy(&c, ptr, sizeof(char)); + ptr += sizeof(char); + v.m_val.cVal = c; + break; + case VT_USHORT: + uint16_t us; + memcpy(&us, ptr, sizeof(uint16_t)); + ptr += sizeof(uint16_t); + v.m_val.uiVal = us; + break; + case VT_ULONG: + uint32_t ul; + memcpy(&ul, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + v.m_val.ulVal = ul; + break; + case VT_ULONGLONG: + uint64_t ull; + memcpy(&ull, ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + v.m_val.ullVal = ull; + break; + case VT_BOOL: + byte bl; + memcpy(&bl, ptr, sizeof(byte)); + ptr += sizeof(byte); + v.m_val.blVal = (bl != 0); + break; + default: + throw IllegalStateException( + "Tools::PropertySet::PropertySet: Deserialization problem." + ); + } + + m_propertySet.insert(std::pair<std::string, Variant>(s, v)); + } +} + +uint32_t Tools::PropertySet::getByteArraySize() +{ + uint32_t size = sizeof(uint32_t); + std::map<std::string, Variant>::iterator it; + + for (it = m_propertySet.begin(); it != m_propertySet.end(); ++it) + { + switch ((*it).second.m_varType) + { + case VT_SHORT: + size += sizeof(int16_t); + break; + case VT_LONG: + size += sizeof(int32_t); + break; + case VT_LONGLONG: + size += sizeof(int64_t); + break; + case VT_BYTE: + size += sizeof(byte); + break; + case VT_FLOAT: + size += sizeof(float); + break; + case VT_DOUBLE: + size += sizeof(double); + break; + case VT_CHAR: + size += sizeof(char); + break; + case VT_USHORT: + size += sizeof(uint16_t); + break; + case VT_ULONG: + size += sizeof(uint32_t); + break; + case VT_ULONGLONG: + size += sizeof(uint64_t); + break; + case VT_BOOL: + size += sizeof(byte); + break; + default: + throw NotSupportedException( + "Tools::PropertySet::getSize: Unknown type." + ); + } + size += static_cast<uint32_t>((*it).first.size()) + 1 + sizeof(VariantType); + } + + return size; +} + +void Tools::PropertySet::storeToByteArray(byte** data, uint32_t& length) +{ + length = getByteArraySize(); + *data = new byte[length]; + byte* ptr = *data; + + uint32_t numberOfProperties = static_cast<uint32_t>(m_propertySet.size()); + memcpy(ptr, &numberOfProperties, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + std::map<std::string, Variant>::iterator it; + + for (it = m_propertySet.begin(); it != m_propertySet.end(); ++it) + { + size_t strSize = (*it).first.size(); + memcpy(ptr, (*it).first.c_str(), strSize); + ptr += strSize; + *ptr = 0; + ++ptr; + + memcpy(ptr, &((*it).second.m_varType), sizeof(VariantType)); + ptr += sizeof(VariantType); + + switch ((*it).second.m_varType) + { + case VT_SHORT: + memcpy(ptr, &((*it).second.m_val.iVal), sizeof(int16_t)); + ptr += sizeof(int16_t); + break; + case VT_LONG: + memcpy(ptr, &((*it).second.m_val.lVal), sizeof(int32_t)); + ptr += sizeof(int32_t); + break; + case VT_LONGLONG: + memcpy(ptr, &((*it).second.m_val.llVal), sizeof(int64_t)); + ptr += sizeof(int64_t); + break; + case VT_BYTE: + memcpy(ptr, &((*it).second.m_val.bVal), sizeof(byte)); + ptr += sizeof(byte); + break; + case VT_FLOAT: + memcpy(ptr, &((*it).second.m_val.fltVal), sizeof(float)); + ptr += sizeof(float); + break; + case VT_DOUBLE: + memcpy(ptr, &((*it).second.m_val.dblVal), sizeof(double)); + ptr += sizeof(double); + break; + case VT_CHAR: + memcpy(ptr, &((*it).second.m_val.cVal), sizeof(char)); + ptr += sizeof(char); + break; + case VT_USHORT: + memcpy(ptr, &((*it).second.m_val.uiVal), sizeof(uint16_t)); + ptr += sizeof(uint16_t); + break; + case VT_ULONG: + memcpy(ptr, &((*it).second.m_val.ulVal), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + break; + case VT_ULONGLONG: + memcpy(ptr, &((*it).second.m_val.ullVal), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + break; + case VT_BOOL: + byte bl; + bl = (*it).second.m_val.blVal; + memcpy(ptr, &bl, sizeof(byte)); + ptr += sizeof(byte); + break; + default: + throw NotSupportedException( + "Tools::PropertySet::getData: Cannot serialize a variant of this type." + ); + } + } + + assert(ptr == (*data) + length); +} + +Tools::Variant Tools::PropertySet::getProperty(std::string property) +{ +// #ifdef HAVE_PTHREAD_H +// Tools::ExclusiveLock lock(&m_rwLock); +// #else +// if (m_rwLock == false) m_rwLock = true; +// else throw Tools::IllegalStateException("getProperty: cannot acquire an shared lock"); +// #endif + + try + { + std::map<std::string, Variant>::iterator it = m_propertySet.find(property); + + if (it != m_propertySet.end()) return (*it).second; + else return Variant(); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void Tools::PropertySet::setProperty(std::string property, Variant& v) +{ +#ifdef HAVE_PTHREAD_H + // Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::EndOfStreamException("setProperty: cannot acquire an exclusive lock"); +#endif + + try + { + std::pair<std::map<std::string, Variant>::iterator, bool> ret; + std::map<std::string, Variant>::iterator it; + + ret = m_propertySet.insert(std::pair<std::string, Variant>(property, v)); + + // If we weren't able to insert because it is already in the map + // update our existing value + if (ret.second == false) ret.first->second = v; + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void Tools::PropertySet::removeProperty(std::string property) +{ +#ifdef HAVE_PTHREAD_H + // Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::EndOfStreamException("setProperty: cannot acquire an exclusive lock"); +#endif + + try + { + std::map<std::string, Variant>::iterator it = m_propertySet.find(property); + if (it != m_propertySet.end()) m_propertySet.erase(it); + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +Tools::Interval::Interval() : m_type(IT_RIGHTOPEN), m_low(0.0), m_high(0.0) +{ +} + +Tools::Interval::Interval(IntervalType t, double l, double h) : m_type(t), m_low(l), m_high(h) +{ + assert(l < h); +} + +Tools::Interval::Interval(double l, double h) : m_type(IT_RIGHTOPEN), m_low(l), m_high(h) +{ + assert(l < h); +} + +Tools::Interval::Interval(const Interval& iv) +{ + m_low = iv.m_low; + m_high = iv.m_high; + m_type = iv.m_type; +} + +Tools::IInterval& Tools::Interval::operator=(const Tools::IInterval& iv) +{ + if (this != &iv) + { + m_low = iv.getLowerBound(); + m_high = iv.getUpperBound(); + m_type = iv.getIntervalType(); + } + + return *this; +} + +bool Tools::Interval::operator==(const Interval& iv) const +{ + if ( + m_type == iv.m_type && + m_low >= iv.m_low - std::numeric_limits<double>::epsilon() && + m_low <= iv.m_low + std::numeric_limits<double>::epsilon() && + m_high >= iv.m_high - std::numeric_limits<double>::epsilon() && + m_high <= iv.m_high + std::numeric_limits<double>::epsilon()) + return true; + + return false; +} + +bool Tools::Interval::operator!=(const Interval& iv) const +{ + return ! (*this == iv); +} + +double Tools::Interval::getLowerBound() const +{ + return m_low; +} + +double Tools::Interval::getUpperBound() const +{ + return m_high; +} + +void Tools::Interval::setBounds(double l, double h) +{ + assert(l <= h); + + m_low = l; + m_high = h; +} + +bool Tools::Interval::intersectsInterval(const IInterval& i) const +{ + return intersectsInterval(i.getIntervalType(), i.getLowerBound(), i.getUpperBound()); +} + +bool Tools::Interval::intersectsInterval(IntervalType type, const double low, const double high) const +{ + if (m_high < m_low) + throw IllegalStateException( + "Tools::Interval::intersectsInterval: high boundary is smaller than low boundary." + ); + + if (m_low > high || m_high < low) return false; + if ((m_low > low && m_low < high) || (m_high > low && m_high < high)) return true; + + switch (m_type) + { + case IT_CLOSED: + if (m_low == high) + { + if (type == IT_CLOSED || type == IT_LEFTOPEN) return true; + else return false; + } + else if (m_high == low) + { + if (type == IT_CLOSED || type == IT_RIGHTOPEN) return true; + else return false; + } + break; + case IT_OPEN: + if (m_low == high || m_high == low) return false; + break; + case IT_RIGHTOPEN: + if (m_low == high) + { + if (type == IT_CLOSED || type == IT_LEFTOPEN) return true; + else return false; + } + else if (m_high == low) + { + return false; + } + break; + case IT_LEFTOPEN: + if (m_low == high) + { + return false; + } + else if (m_high == low) + { + if (type == IT_CLOSED || type == IT_RIGHTOPEN) return true; + else return false; + } + break; + } + + return true; +} + +bool Tools::Interval::containsInterval(const IInterval& i) const +{ + if (m_high < m_low) + throw IllegalStateException( + "Tools::Interval::containsInterval: high boundary is smaller than low boundary." + ); + + double low = i.getLowerBound(); + double high = i.getUpperBound(); + IntervalType type = i.getIntervalType(); + + if (m_low < low && m_high > high) return true; + if (m_low > low || m_high < high) return false; + + switch (m_type) + { + case IT_CLOSED: + break; + case IT_OPEN: + if ((m_low == low && m_high == high && type != IT_OPEN) || + (m_low == low && (type == IT_CLOSED || type == IT_RIGHTOPEN)) || + (m_high == high && ( type == IT_CLOSED || type == IT_LEFTOPEN))) + return false; + break; + case IT_RIGHTOPEN: + if (m_high == high && (type == IT_CLOSED || type == IT_LEFTOPEN)) + return false; + break; + case IT_LEFTOPEN: + if (m_low == low && (type == IT_CLOSED || type == IT_RIGHTOPEN)) + return false; + break; + } + + return true; +} + +Tools::IntervalType Tools::Interval::getIntervalType() const +{ + return m_type; +} + +Tools::Random::Random() +{ + m_pBuffer = 0; + initDrand(static_cast<uint32_t>(time(0)), 0xD31A); +} + +Tools::Random::Random(uint32_t seed, uint16_t xsubi0) +{ + m_pBuffer = 0; + initDrand(seed, xsubi0); +} + +Tools::Random::~Random() +{ + delete[] m_pBuffer; +} + +void Tools::Random::initDrand(uint32_t seed, uint16_t xsubi0) +{ + m_pBuffer = new uint16_t[3]; + m_pBuffer[0] = static_cast<uint16_t>(xsubi0); + uint32_t mask = 0xFFFF; + m_pBuffer[1] = static_cast<uint16_t>(seed & mask); + mask = mask << 16; + m_pBuffer[2] = static_cast<uint16_t>((seed & mask) >> 16); + +#ifdef BUILD_OS_CYGWIN + srand48(*(reinterpret_cast<uint32_t*>(m_pBuffer))); + // BUG: There is a bug in cygwin gcc 3.4.4. srand48 needs to be called + // even if we are using the functions that take the seed as a parameter. + // This does not affect random number generation, which still happens + // using the seed provided as a parameter and not the one provided to srand48 :-S +#endif +} + +int32_t Tools::Random::nextUniformLong() +{ + return jrand48(m_pBuffer); +} + +uint32_t Tools::Random::nextUniformUnsignedLong() +{ + return static_cast<uint32_t>(nextUniformLong()); +} + +int32_t Tools::Random::nextUniformLong(int32_t low, int32_t high) +{ + return low + static_cast<int32_t>((high - low) * nextUniformDouble()); +} + +uint32_t Tools::Random::nextUniformUnsignedLong(uint32_t low, uint32_t high) +{ + return low + static_cast<uint32_t>((high - low) * nextUniformDouble()); +} + +int64_t Tools::Random::nextUniformLongLong() +{ + return static_cast<int64_t>(nextUniformUnsignedLongLong()); +} + +uint64_t Tools::Random::nextUniformUnsignedLongLong() +{ + uint64_t lh = static_cast<uint64_t>(nextUniformLong()); + uint64_t ll = static_cast<uint64_t>(nextUniformLong()); + uint64_t ret = (lh << 32) | ll; + return ret; +} + +int64_t Tools::Random::nextUniformLongLong(int64_t low, int64_t high) +{ + return low + static_cast<int64_t>((high - low) * nextUniformDouble()); +} + +uint64_t Tools::Random::nextUniformUnsignedLongLong(uint64_t low, uint64_t high) +{ + return low + static_cast<uint64_t>((high - low) * nextUniformDouble()); +} + +int16_t Tools::Random::nextUniformShort() +{ + return static_cast<int16_t>(nextUniformUnsignedShort()); +} + +uint16_t Tools::Random::nextUniformUnsignedShort() +{ + return nextUniformUnsignedLong() >> 16; + // retain the high order bits. +} + +double Tools::Random::nextUniformDouble() +{ + uint16_t* xsubi = reinterpret_cast<uint16_t*>(m_pBuffer); + return erand48(xsubi); +} + +double Tools::Random::nextUniformDouble(double low, double high) +{ + return (high - low) * nextUniformDouble() + low; +} + +bool Tools::Random::flipCoin() +{ + if (nextUniformDouble() < 0.5) return true; + return false; +} + +#if HAVE_PTHREAD_H +Tools::SharedLock::SharedLock(pthread_rwlock_t* pLock) + : m_pLock(pLock) +{ + pthread_rwlock_rdlock(m_pLock); +} + +Tools::SharedLock::~SharedLock() +{ + pthread_rwlock_unlock(m_pLock); +} + +Tools::ExclusiveLock::ExclusiveLock(pthread_rwlock_t* pLock) + : m_pLock(pLock) +{ + pthread_rwlock_wrlock(m_pLock); +} + +Tools::ExclusiveLock::~ExclusiveLock() +{ + pthread_rwlock_unlock(m_pLock); +} +#endif + +std::ostream& Tools::operator<<(std::ostream& os, const Tools::PropertySet& p) +{ + std::map<std::string, Variant>::const_iterator it; + + for (it = p.m_propertySet.begin(); it != p.m_propertySet.end(); ++it) + { + if (it != p.m_propertySet.begin()) os << ", "; + + switch ((*it).second.m_varType) + { + case VT_LONG: + os << (*it).first << ": " << (*it).second.m_val.lVal; + break; + case VT_LONGLONG: + os << (*it).first << ": " << (*it).second.m_val.llVal; + break; + case VT_BYTE: + os << (*it).first << ": " << (*it).second.m_val.bVal; + break; + case VT_SHORT: + os << (*it).first << ": " << (*it).second.m_val.iVal; + break; + case VT_FLOAT: + os << (*it).first << ": " << (*it).second.m_val.fltVal; + break; + case VT_DOUBLE: + os << (*it).first << ": " << (*it).second.m_val.dblVal; + break; + case VT_CHAR: + os << (*it).first << ": " << (*it).second.m_val.cVal; + break; + case VT_USHORT: + os << (*it).first << ": " << (*it).second.m_val.uiVal; + break; + case VT_ULONG: + os << (*it).first << ": " << (*it).second.m_val.ulVal; + break; + case VT_ULONGLONG: + os << (*it).first << ": " << (*it).second.m_val.ullVal; + break; + case VT_BOOL: + os << (*it).first << ": " << (*it).second.m_val.blVal; + break; + case VT_PCHAR: + os << (*it).first << ": " << (*it).second.m_val.pcVal; + break; + case VT_PVOID: + os << (*it).first << ": ?"; + break; + case VT_EMPTY: + os << (*it).first << ": empty"; + break; + default: + os << (*it).first << ": unknown"; + } + } + + return os; +} + +std::ostream& Tools::operator<<(std::ostream& os, const Tools::Interval& iv) +{ + os << iv.m_type << " " << iv.m_low << " " << iv.m_high; + return os; +} + +// +// BufferedFile +// +Tools::BufferedFile::BufferedFile(uint32_t u32BufferSize) +: m_buffer(new char[u32BufferSize]), m_u32BufferSize(u32BufferSize), m_bEOF(true) +{ +} + +Tools::BufferedFile::~BufferedFile() +{ + m_file.close(); + delete[] m_buffer; +} + +void Tools::BufferedFile::close() +{ + m_file.close(); +} + +bool Tools::BufferedFile::eof() +{ + return m_bEOF; +} + +// +// BufferedFileReader +// +Tools::BufferedFileReader::BufferedFileReader() +{ +} + +Tools::BufferedFileReader::BufferedFileReader(const std::string& sFileName, uint32_t u32BufferSize) +: BufferedFile(u32BufferSize) +{ + open(sFileName); +} + +void Tools::BufferedFileReader::open(const std::string& sFileName) +{ + m_bEOF = false; + m_file.close(); m_file.clear(); + + + m_file.open(sFileName.c_str(), std::ios_base::in | std::ios_base::binary); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileReader::BufferedFileReader: Cannot open file."); + + m_file.rdbuf()->pubsetbuf(m_buffer, m_u32BufferSize); +} + +Tools::BufferedFileReader::~BufferedFileReader() +{ +} + +void Tools::BufferedFileReader::rewind() +{ + m_file.clear(); + m_file.seekg(0, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileReader::rewind: seek failed."); + + m_bEOF = false; +} + +void Tools::BufferedFileReader::seek(std::fstream::off_type offset) +{ + m_bEOF = false; + m_file.clear(); + m_file.seekg(offset, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileReader::seek: seek failed."); +} + +uint8_t Tools::BufferedFileReader::readUInt8() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint8_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint8_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +uint16_t Tools::BufferedFileReader::readUInt16() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint16_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint16_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +uint32_t Tools::BufferedFileReader::readUInt32() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint32_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint32_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +uint64_t Tools::BufferedFileReader::readUInt64() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint64_t ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(uint64_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +float Tools::BufferedFileReader::readFloat() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + float ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(float)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +double Tools::BufferedFileReader::readDouble() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + double ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(double)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +bool Tools::BufferedFileReader::readBoolean() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + bool ret; + m_file.read(reinterpret_cast<char*>(&ret), sizeof(bool)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + return ret; +} + +std::string Tools::BufferedFileReader::readString() +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + uint32_t len; + m_file.read(reinterpret_cast<char*>(&len), sizeof(uint32_t)); + if (! m_file.good()) + { + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + + std::string::value_type* buf = new std::string::value_type[len]; + m_file.read(reinterpret_cast<char*>(buf), len * sizeof(std::string::value_type)); + if (! m_file.good()) + { + delete[] buf; + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } + + std::string ret(buf, len); + delete[] buf; + + return ret; +} + +void Tools::BufferedFileReader::readBytes(uint32_t u32Len, byte** pData) +{ + if (m_bEOF) throw Tools::EndOfStreamException(""); + + *pData = new byte[u32Len]; + m_file.read(reinterpret_cast<char*>(*pData), u32Len); + if (! m_file.good()) + { + delete[] *pData; + m_bEOF = true; + throw Tools::EndOfStreamException(""); + } +} + +// +// BufferedFileWriter +// +Tools::BufferedFileWriter::BufferedFileWriter() +{ + open(""); +} + +Tools::BufferedFileWriter::BufferedFileWriter(const std::string& sFileName, FileMode mode, uint32_t u32BufferSize) +: BufferedFile(u32BufferSize) +{ + open(sFileName, mode); +} + +Tools::BufferedFileWriter::~BufferedFileWriter() +{ + m_file.flush(); +} + +void Tools::BufferedFileWriter::open(const std::string& sFileName, FileMode mode) +{ + m_bEOF = false; + m_file.close(); m_file.clear(); + + if (mode == CREATE) + { + m_file.open(sFileName.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file."); + } + else if (mode == APPEND) + { + // Idiotic fstream::open truncates an existing file anyway, if it is only opened + // for output (no ios_base::in flag)!! On the other hand, if a file does not exist + // and the ios_base::in flag is specified, then the open fails!! + + m_file.open(sFileName.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (! m_file.good()) + { + m_file.clear(); + m_file.open(sFileName.c_str(), std::ios_base::out | std::ios_base::binary); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file."); + } + else + { + m_file.seekp(0, std::ios_base::end); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::open: Cannot open file."); + } + } + else + throw Tools::IllegalArgumentException("Tools::BufferedFileWriter::open: Unknown mode."); +} + +void Tools::BufferedFileWriter::rewind() +{ + m_bEOF = false; + m_file.clear(); + m_file.seekp(0, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::rewind: seek failed."); +} + +void Tools::BufferedFileWriter::seek(std::fstream::off_type offset) +{ + m_bEOF = false; + m_file.clear(); + m_file.seekp(offset, std::ios_base::beg); + if (! m_file.good()) + throw std::ios_base::failure("Tools::BufferedFileWriter::seek: seek failed."); +} + +void Tools::BufferedFileWriter::write(uint8_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint8_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint16_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint16_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint32_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint32_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint64_t i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(uint64_t)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(float i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(float)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(double i) +{ + m_file.write(reinterpret_cast<const char*>(&i), sizeof(double)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(bool b) +{ + m_file.write(reinterpret_cast<const char*>(&b), sizeof(bool)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(const std::string& s) +{ + uint32_t len = static_cast<uint32_t>(s.size()); + m_file.write(reinterpret_cast<const char*>(&len), sizeof(uint32_t)); + if (! m_file.good()) throw std::ios_base::failure(""); + m_file.write(reinterpret_cast<const char*>(s.c_str()), len * sizeof(std::string::value_type)); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +void Tools::BufferedFileWriter::write(uint32_t u32Len, byte* pData) +{ + m_file.write(reinterpret_cast<const char*>(pData), u32Len); + if (! m_file.good()) throw std::ios_base::failure(""); +} + +// +// TemporaryFile +// +Tools::TemporaryFile::TemporaryFile() +{ + +#ifdef _MSC_VER + +#ifndef L_tmpnam_s +// MSVC 2003 doesn't have tmpnam_s, so we'll have to use the old functions + + char* tmpName = NULL; + tmpName = tmpnam( NULL ); + + if (tmpName == NULL) + throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name."); + +#else + char tmpName[L_tmpnam_s]; + errno_t err = tmpnam_s(tmpName, L_tmpnam_s); + if (err) + throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name."); + +#endif + if (tmpName[0] == '\\') + m_sFile = std::string(tmpName + 1); + else + m_sFile = std::string(tmpName); + +#else + char tmpName[7] = "XXXXXX"; + if (mktemp(tmpName) == 0) + throw std::ios_base::failure("Tools::TemporaryFile: Cannot create temporary file name."); + m_sFile = tmpName; +#endif + + m_pFile = new Tools::BufferedFileWriter(m_sFile, Tools::CREATE); +} + +Tools::TemporaryFile::~TemporaryFile() +{ + delete m_pFile; + +#ifdef _MSC_VER + _unlink(m_sFile.c_str()); +#else + std::remove(m_sFile.c_str()); +#endif +} + +void Tools::TemporaryFile::rewindForReading() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br != 0) + m_pFile->rewind(); + else + { + delete m_pFile; + m_pFile = new Tools::BufferedFileReader(m_sFile); + } +} + +void Tools::TemporaryFile::rewindForWriting() +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw != 0) + m_pFile->rewind(); + else + { + delete m_pFile; + m_pFile = new Tools::BufferedFileWriter(m_sFile); + } +} + +bool Tools::TemporaryFile::eof() +{ + return m_pFile->eof(); +} + +std::string Tools::TemporaryFile::getFileName() const +{ + return m_sFile; +} + +uint8_t Tools::TemporaryFile::readUInt8() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt8: file not open for reading."); + + return br->readUInt8(); +} + +uint16_t Tools::TemporaryFile::readUInt16() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt16: file not open for reading."); + + return br->readUInt16(); +} + +uint32_t Tools::TemporaryFile::readUInt32() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt32: file not open for reading."); + + return br->readUInt32(); +} + +uint64_t Tools::TemporaryFile::readUInt64() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readUInt64: file not open for reading."); + + return br->readUInt64(); +} + +float Tools::TemporaryFile::readFloat() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readFloat: file not open for reading."); + + return br->readFloat(); +} + +double Tools::TemporaryFile::readDouble() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readDouble: file not open for reading."); + + return br->readDouble(); +} + +std::string Tools::TemporaryFile::readString() +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readString: file not open for reading."); + + return br->readString(); +} + +void Tools::TemporaryFile::readBytes(uint32_t u32Len, byte** pData) +{ + Tools::BufferedFileReader* br = dynamic_cast<Tools::BufferedFileReader*>(m_pFile); + if (br == 0) + throw std::ios_base::failure("Tools::TemporaryFile::readString: file not open for reading."); + + return br->readBytes(u32Len, pData); +} + +void Tools::TemporaryFile::write(uint8_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(uint16_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(uint32_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(uint64_t i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(float i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(double i) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(i); +} + +void Tools::TemporaryFile::write(const std::string& s) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(s); +} + +void Tools::TemporaryFile::write(uint32_t u32Len, byte* pData) +{ + Tools::BufferedFileWriter* bw = dynamic_cast<Tools::BufferedFileWriter*>(m_pFile); + if (bw == 0) + throw std::ios_base::failure("Tools::TemporaryFile::write: file not open for writing."); + + return bw->write(u32Len, pData); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tools/rand48.cc b/sci-libs/libspatialindex/svn/trunk/src/tools/rand48.cc new file mode 100644 index 000000000..cc406019d --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tools/rand48.cc @@ -0,0 +1,145 @@ +/* +* Copyright (c) 1993 Martin Birgmeier +* All rights reserved. +* +* You may redistribute unmodified or modified versions of this source +* code provided that the above copyright notice and this and the +* following conditions are retained. +* +* This software is provided ``as is'', and comes with no warranties +* of any kind. I shall in no event be liable for anything that happens +* to anyone/anything when using this software. +*/ + +#include <math.h> +#include <stdlib.h> + +#define RAND48_SEED_0 (0x330e) +#define RAND48_SEED_1 (0xabcd) +#define RAND48_SEED_2 (0x1234) +#define RAND48_MULT_0 (0xe66d) +#define RAND48_MULT_1 (0xdeec) +#define RAND48_MULT_2 (0x0005) +#define RAND48_ADD (0x000b) + + + /* Internal function to compute next state of the generator. */ +static void _dorand48(unsigned short[3]); + +/* Unfortunately, 3 __globals, which the exported functions must access */ +unsigned short __rand48_Seed[3] = { + RAND48_SEED_0, + RAND48_SEED_1, + RAND48_SEED_2 +}; +unsigned short __rand48_Mult[3] = { + RAND48_MULT_0, + RAND48_MULT_1, + RAND48_MULT_2 +}; +unsigned short __rand48_Add = RAND48_ADD; + +/* Internal function to compute next state of the generator. */ + static void +_dorand48(unsigned short xseed[3]) +{ + unsigned long accu; + unsigned short temp[2]; + + accu = (unsigned long) __rand48_Mult[0] * (unsigned long) xseed[0] + + (unsigned long) __rand48_Add; + temp[0] = (unsigned short) accu; /* lower 16 bits */ + accu >>= sizeof(unsigned short) * 8; + accu += (unsigned long) __rand48_Mult[0] * (unsigned long) xseed[1] + + (unsigned long) __rand48_Mult[1] * (unsigned long) xseed[0]; + temp[1] = (unsigned short) accu; /* middle 16 bits */ + accu >>= sizeof(unsigned short) * 8; + accu += __rand48_Mult[0] * xseed[2] + __rand48_Mult[1] * xseed[1] + + __rand48_Mult[2] * xseed[0]; + xseed[0] = temp[0]; + xseed[1] = temp[1]; + xseed[2] = (unsigned short) accu; +} + + extern void +srand48(long seed) +{ + __rand48_Seed[0] = RAND48_SEED_0; + __rand48_Seed[1] = (unsigned short) seed; + __rand48_Seed[2] = (unsigned short) (seed >> 16); + __rand48_Mult[0] = RAND48_MULT_0; + __rand48_Mult[1] = RAND48_MULT_1; + __rand48_Mult[2] = RAND48_MULT_2; + __rand48_Add = RAND48_ADD; +} + + extern unsigned short * +seed48(unsigned short xseed[3]) +{ + static unsigned short sseed[3]; + + sseed[0] = __rand48_Seed[0]; + sseed[1] = __rand48_Seed[1]; + sseed[2] = __rand48_Seed[2]; + __rand48_Seed[0] = xseed[0]; + __rand48_Seed[1] = xseed[1]; + __rand48_Seed[2] = xseed[2]; + __rand48_Mult[0] = RAND48_MULT_0; + __rand48_Mult[1] = RAND48_MULT_1; + __rand48_Mult[2] = RAND48_MULT_2; + __rand48_Add = RAND48_ADD; + return sseed; +} + + extern long +nrand48(unsigned short xseed[3]) +{ + _dorand48(xseed); + return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1); +} + extern long +mrand48(void) +{ + _dorand48(__rand48_Seed); + return ((long) __rand48_Seed[2] << 16) + (long) __rand48_Seed[1]; +} + + extern long +lrand48(void) +{ + _dorand48(__rand48_Seed); + return ((long) __rand48_Seed[2] << 15) + ((long) __rand48_Seed[1] >> 1); +} + + extern void +lcong48(unsigned short p[7]) +{ + __rand48_Seed[0] = p[0]; + __rand48_Seed[1] = p[1]; + __rand48_Seed[2] = p[2]; + __rand48_Mult[0] = p[3]; + __rand48_Mult[1] = p[4]; + __rand48_Mult[2] = p[5]; + __rand48_Add = p[6]; +} + extern long +jrand48(unsigned short xseed[3]) +{ + _dorand48(xseed); + return ((long) xseed[2] << 16) + (long) xseed[1]; +} + + extern double +erand48(unsigned short xseed[3]) +{ + _dorand48(xseed); + return ldexp((double) xseed[0], -48) + + ldexp((double) xseed[1], -32) + + ldexp((double) xseed[2], -16); +} + + extern double +drand48(void) +{ + return erand48(__rand48_Seed); +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/all-wcprops b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/all-wcprops new file mode 100644 index 000000000..d0b7228b9 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/all-wcprops @@ -0,0 +1,77 @@ +K 25 +svn:wc:ra_dav:version-url +V 57 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/tprtree +END +Statistics.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/Statistics.h +END +PointerPoolNode.h +K 25 +svn:wc:ra_dav:version-url +V 75 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/PointerPoolNode.h +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/45/spatialindex/trunk/src/tprtree/Makefile.am +END +Node.cc +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/tprtree/Node.cc +END +TPRTree.cc +K 25 +svn:wc:ra_dav:version-url +V 68 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/tprtree/TPRTree.cc +END +Index.cc +K 25 +svn:wc:ra_dav:version-url +V 66 +/spatialindex/!svn/ver/159/spatialindex/trunk/src/tprtree/Index.cc +END +Leaf.cc +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/Leaf.cc +END +Node.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/Node.h +END +TPRTree.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/spatialindex/!svn/ver/133/spatialindex/trunk/src/tprtree/TPRTree.h +END +Index.h +K 25 +svn:wc:ra_dav:version-url +V 65 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/Index.h +END +Leaf.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/Leaf.h +END +Statistics.cc +K 25 +svn:wc:ra_dav:version-url +V 71 +/spatialindex/!svn/ver/130/spatialindex/trunk/src/tprtree/Statistics.cc +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/dir-prop-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/dir-prop-base new file mode 100644 index 000000000..ea9b95e8a --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/dir-prop-base @@ -0,0 +1,9 @@ +K 10 +svn:ignore +V 33 +Makefile.in +.libs +.deps +Makefile + +END diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/entries b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/entries new file mode 100644 index 000000000..370b2ac09 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/entries @@ -0,0 +1,436 @@ +10 + +dir +203 +http://svn.gispython.org/spatialindex/spatialindex/trunk/src/tprtree +http://svn.gispython.org/spatialindex + + + +2009-11-02T20:08:16.754818Z +159 +hobu +has-props + + + + + + + + + + + + + +619784c2-a736-0410-9738-aa60efc94a9c + +Statistics.h +file + + + + +2011-08-01T00:42:34.734138Z +a9369e45f996375d76e118a00d438f6c +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2269 + +PointerPoolNode.h +file + + + + +2011-08-01T00:42:34.734138Z +a97ebd375163a3bee8d1cf56222f0671 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2676 + +Makefile.am +file + + + + +2011-08-01T00:42:34.734138Z +3289458f71d69c2203543185e34a605d +2008-01-17T23:34:01.575758Z +45 +hobu + + + + + + + + + + + + + + + + + + + + + +274 + +Node.cc +file + + + + +2011-08-01T00:42:34.734138Z +27dfacbf070d76b0c85114c65f0c76eb +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +36860 + +TPRTree.cc +file + + + + +2011-08-01T00:42:34.734138Z +39fc26a49ea18f3271482e1ba30f9bb1 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +38446 + +Index.cc +file + + + + +2011-08-01T00:42:34.734138Z +b3f77c3ed0dce9c492b40f850c1eeb20 +2009-11-02T20:08:16.754818Z +159 +hobu + + + + + + + + + + + + + + + + + + + + + +12394 + +Leaf.cc +file + + + + +2011-08-01T00:42:34.737159Z +28860ef91f5b5b1a1f10b2da9b0bd24c +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +4193 + +Node.h +file + + + + +2011-08-01T00:42:34.741160Z +deb8036556b5969f5f10470683e6b5c6 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +6487 + +TPRTree.h +file + + + + +2011-08-01T00:42:34.741160Z +d812837a69ec25ea163a6b254386a211 +2009-08-14T15:19:40.553411Z +133 +hobu + + + + + + + + + + + + + + + + + + + + + +6862 + +Index.h +file + + + + +2011-08-01T00:42:34.741160Z +1a71065318767017c849ceb14b3acbb3 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +2216 + +Leaf.h +file + + + + +2011-08-01T00:42:34.741160Z +f548d3c8d8ff0a8245013b1380d7921c +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +1483 + +Statistics.cc +file + + + + +2011-08-01T00:42:34.741160Z +e93804de428f2bffd1e5a1672cd36a52 +2009-08-13T15:24:35.589450Z +130 +mhadji + + + + + + + + + + + + + + + + + + + + + +3591 + diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Index.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Index.cc.svn-base new file mode 100644 index 000000000..574414812 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Index.cc.svn-base @@ -0,0 +1,400 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "TPRTree.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" + +using namespace SpatialIndex::TPRTree; + +Index::~Index() +{ +} + +Index::Index(SpatialIndex::TPRTree::TPRTree* pTree, id_type id, uint32_t level) : Node(pTree, id, level, pTree->m_indexCapacity) +{ +} + +NodePtr Index::chooseSubtree(const MovingRegion& mbr, uint32_t insertionLevel, std::stack<id_type>& pathBuffer) +{ + if (m_level == insertionLevel) return NodePtr(this, &(m_pTree->m_indexPool)); + + pathBuffer.push(m_identifier); + + uint32_t child = 0; + + switch (m_pTree->m_treeVariant) + { + case TPRV_RSTAR: + if (m_level == 1) + { + // if this node points to leaves... + child = findLeastOverlap(mbr); + } + else + { + child = findLeastEnlargement(mbr); + } + break; + default: + throw Tools::NotSupportedException("Index::chooseSubtree: Tree variant not supported."); + } + assert(child != std::numeric_limits<uint32_t>::max()); + + NodePtr n = m_pTree->readNode(m_pIdentifier[child]); + NodePtr ret = n->chooseSubtree(mbr, insertionLevel, pathBuffer); + assert(n.unique()); + if (ret.get() == n.get()) n.relinquish(); + + return ret; +} + +NodePtr Index::findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_ptrMBR[cChild]->containsRegionAfterTime(m_pTree->m_currentTime, mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findLeaf(mbr, id, pathBuffer); + if (n.get() == l.get()) n.relinquish(); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} + +void Index::split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight) +{ + ++(m_pTree->m_stats.m_splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case TPRV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Index::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_indexPool.acquire(); + pRight = m_pTree->m_indexPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Index(m_pTree, m_identifier, m_level), &(m_pTree->m_indexPool)); + if (pRight.get() == 0) pRight = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(0, 0, *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(0, 0, *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + } +} + +uint32_t Index::findLeastEnlargement(const MovingRegion& r) const +{ + double area = std::numeric_limits<double>::max(); + uint32_t best = std::numeric_limits<uint32_t>::max(); + + MovingRegionPtr t = m_pTree->m_regionPool.acquire(); + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // I need the combined region from current time up to infinity here. + m_ptrMBR[cChild]->getCombinedRegionAfterTime(ivT.getLowerBound(), *t, r); + + double a = m_ptrMBR[cChild]->getAreaInTime(ivT); + double b = t->getAreaInTime(ivT); + double enl = b - a; + + if (enl < area) + { + area = enl; + best = cChild; + } + else if (enl == area) + { + // this will rarely happen, so compute best area on the fly only + // when necessary. + if (a < m_ptrMBR[best]->getAreaInTime(ivT)) best = cChild; + } + } + + return best; +} + +uint32_t Index::findLeastOverlap(const MovingRegion& r) const +{ + OverlapEntry** entries = new OverlapEntry*[m_children]; + + double leastOverlap = std::numeric_limits<double>::max(); + double me = std::numeric_limits<double>::max(); + OverlapEntry* best = 0; + + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + // find combined region and enlargement of every entry and store it. + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + try + { + entries[cChild] = new OverlapEntry(); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete entries[i]; + delete[] entries; + throw; + } + + entries[cChild]->m_index = cChild; + entries[cChild]->m_original = m_ptrMBR[cChild]; + entries[cChild]->m_combined = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->getCombinedRegionAfterTime(m_pTree->m_currentTime, *(entries[cChild]->m_combined), r); + entries[cChild]->m_oa = entries[cChild]->m_original->getAreaInTime(ivT); + entries[cChild]->m_ca = entries[cChild]->m_combined->getAreaInTime(ivT); + entries[cChild]->m_enlargement = entries[cChild]->m_ca - entries[cChild]->m_oa; + + if (entries[cChild]->m_enlargement < me) + { + me = entries[cChild]->m_enlargement; + best = entries[cChild]; + } + else if (entries[cChild]->m_enlargement == me && entries[cChild]->m_oa < best->m_oa) + { + best = entries[cChild]; + } + } + + if (me < -std::numeric_limits<double>::epsilon() || me > std::numeric_limits<double>::epsilon()) + { + uint32_t cIterations; + + if (m_children > m_pTree->m_nearMinimumOverlapFactor) + { + // sort entries in increasing order of enlargement. + ::qsort(entries, m_children, + sizeof(OverlapEntry*), + OverlapEntry::compareEntries); + assert(entries[0]->m_enlargement <= entries[m_children - 1]->m_enlargement); + + cIterations = m_pTree->m_nearMinimumOverlapFactor; + } + else + { + cIterations = m_children; + } + + // calculate overlap of most important original entries (near minimum overlap cost). + for (uint32_t cIndex = 0; cIndex < cIterations; ++cIndex) + { + double dif = 0.0; + OverlapEntry* e = entries[cIndex]; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (e->m_index != cChild) + { + double f = e->m_combined->getIntersectingAreaInTime(ivT, *(m_ptrMBR[cChild])); + if (f != 0.0) dif += f - e->m_original->getIntersectingAreaInTime(ivT, *(m_ptrMBR[cChild])); + } + } // for (cChild) + + if (dif < leastOverlap) + { + leastOverlap = dif; + best = entries[cIndex]; + } + else if (dif == leastOverlap) + { + if (e->m_enlargement == best->m_enlargement) + { + // keep the one with least area. + if (e->m_original->getAreaInTime(ivT) < best->m_original->getAreaInTime(ivT)) best = entries[cIndex]; + } + else + { + // keep the one with least enlargement. + if (e->m_enlargement < best->m_enlargement) best = entries[cIndex]; + } + } + } // for (cIndex) + } + + uint32_t ret = best->m_index; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + delete entries[cChild]; + } + delete[] entries; + + return ret; +} + +void Index::adjustTree(Node* n, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n->m_identifier) break; + } + assert(child < m_children); + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + //Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + //bool bContained = m_nodeMBR.containsRegionInTime(ivT, n->m_nodeMBR); + + *(m_ptrMBR[child]) = n->m_nodeMBR; + + //if (! bContained) + //{ + // update the MBR at the current time anyway, to make tighter. + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + //} + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, *(m_ptrMBR[cChild])) == true); + } +#endif + + m_pTree->writeNode(this); + + if (/*! bContained && */ ! pathBuffer.empty()) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} + +void Index::adjustTree(Node* n1, Node* n2, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + ++(m_pTree->m_stats.m_adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n1->m_identifier) break; + } + assert(child < m_children); + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + //Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + //bool bContained = m_nodeMBR.containsRegionInTime(ivT, n1->m_nodeMBR); + + *(m_ptrMBR[child]) = n1->m_nodeMBR; + + //if (! bContaied) + //{ + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + //} + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, *(m_ptrMBR[cChild])) == true); + } +#endif + + // No write necessary here. insertData will write the node if needed. + //m_pTree->writeNode(this); + + bool bAdjusted = insertData(0, 0, n2->m_nodeMBR, n2->m_identifier, pathBuffer, overflowTable); + + // if n2 is contained in the node and there was no split or reinsert, + // we need to adjust only if recalculation took place. + // In all other cases insertData above took care of adjustment. + if (! bAdjusted && ! pathBuffer.empty()) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Index.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Index.h.svn-base new file mode 100644 index 000000000..68ca1f51f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Index.h.svn-base @@ -0,0 +1,73 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class Index : public Node + { + public: + virtual ~Index(); + + private: + Index(TPRTree* pTree, id_type id, uint32_t level); + + virtual NodePtr chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& left, NodePtr& right); + + uint32_t findLeastEnlargement(const MovingRegion&) const; + uint32_t findLeastOverlap(const MovingRegion&) const; + + void adjustTree(Node*, std::stack<id_type>&); + void adjustTree(Node*, Node*, std::stack<id_type>&, byte* overflowTable); + + class OverlapEntry + { + public: + uint32_t m_index; + double m_enlargement; + MovingRegionPtr m_original; + MovingRegionPtr m_combined; + double m_oa; + double m_ca; + + static int compareEntries(const void* pv1, const void* pv2) + { + OverlapEntry* pe1 = * (OverlapEntry**) pv1; + OverlapEntry* pe2 = * (OverlapEntry**) pv2; + + if (pe1->m_enlargement < pe2->m_enlargement) return -1; + if (pe1->m_enlargement > pe2->m_enlargement) return 1; + return 0; + } + }; // OverlapEntry + + friend class TPRTree; + friend class Node; + friend class BulkLoader; + }; // Index + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Leaf.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Leaf.cc.svn-base new file mode 100644 index 000000000..a9db9df2c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Leaf.cc.svn-base @@ -0,0 +1,135 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "TPRTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::TPRTree; + +Leaf::~Leaf() +{ +} + +Leaf::Leaf(SpatialIndex::TPRTree::TPRTree* pTree, id_type id) + : Node(pTree, id, 0, pTree->m_leafCapacity) +{ +} + +NodePtr Leaf::chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) +{ + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + return NodePtr(this, &(m_pTree->m_leafPool)); +} + +NodePtr Leaf::findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + if (m_pIdentifier[cChild] == id /*&& mbr == *(m_ptrMBR[cChild])*/) return NodePtr(this, &(m_pTree->m_leafPool)); + } + + return NodePtr(); +} + +void Leaf::split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight) +{ + ++(m_pTree->m_stats.m_splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case TPRV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Leaf::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_leafPool.acquire(); + pRight = m_pTree->m_leafPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + if (pRight.get() == 0) pRight = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(m_pDataLength[g1[cIndex]], m_pData[g1[cIndex]], *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g1[cIndex]] = 0; + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(m_pDataLength[g2[cIndex]], m_pData[g2[cIndex]], *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g2[cIndex]] = 0; + } +} + +void Leaf::deleteData(id_type id, std::stack<id_type>& pathBuffer) +{ + uint32_t child; + + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == id) break; + } + + deleteEntry(child); + m_pTree->writeNode(this); + + std::stack<NodePtr> toReinsert; + NodePtr ptrThis(this, &(m_pTree->m_leafPool)); + condenseTree(toReinsert, pathBuffer, ptrThis); + ptrThis.relinquish(); + + // re-insert eliminated nodes. + while (! toReinsert.empty()) + { + NodePtr n = toReinsert.top(); toReinsert.pop(); + m_pTree->deleteNode(n.get()); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + // keep this in the for loop. The tree height might change after insertions. + byte* overflowTable = new byte[m_pTree->m_stats.m_treeHeight]; + bzero(overflowTable, m_pTree->m_stats.m_treeHeight); + m_pTree->insertData_impl(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild], n->m_level, overflowTable); + n->m_pData[cChild] = 0; + delete[] overflowTable; + } + if (n.get() == this) n.relinquish(); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Leaf.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Leaf.h.svn-base new file mode 100644 index 000000000..01a0bd53c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Leaf.h.svn-base @@ -0,0 +1,47 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class Leaf : public Node + { + public: + virtual ~Leaf(); + + private: + Leaf(TPRTree* pTree, id_type id); + + virtual NodePtr chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& left, NodePtr& right); + + virtual void deleteData(id_type id, std::stack<id_type>& pathBuffer); + + friend class TPRTree; + friend class BulkLoader; + }; // Leaf + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Makefile.am.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Makefile.am.svn-base new file mode 100644 index 000000000..6f6a87aa2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libtprtree.la +INCLUDES = -I../../include +libtprtree_la_SOURCES = Index.cc Leaf.cc Node.cc TPRTree.cc Statistics.cc Leaf.h Index.h Node.h PointerPoolNode.h Statistics.h TPRTree.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Node.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Node.cc.svn-base new file mode 100644 index 000000000..1c14b99c2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Node.cc.svn-base @@ -0,0 +1,1253 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "TPRTree.h" +#include "Node.h" +#include "Index.h" + +using namespace SpatialIndex::TPRTree; + +// +// Tools::IObject interface +// +Tools::IObject* Node::clone() +{ + throw Tools::NotSupportedException("IObject::clone should never be called."); +} + +// +// Tools::ISerializable interface +// +uint32_t Node::getByteArraySize() +{ + return + (sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(double) + + (m_children * (4 * m_pTree->m_dimension * sizeof(double) + sizeof(double) + sizeof(id_type) + sizeof(uint32_t))) + + m_totalDataLength + + (4 * m_pTree->m_dimension * sizeof(double))); +} + +void Node::loadFromByteArray(const byte* ptr) +{ + m_nodeMBR = m_pTree->m_infiniteRegion; + + // skip the node type information, it is not needed. + ptr += sizeof(uint32_t); + + memcpy(&m_level, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&m_children, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&(m_nodeMBR.m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + //memcpy(&(m_nodeMBR.m_endTime), ptr, sizeof(double)); + //ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_ptrMBR[cChild] = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->makeDimension(m_pTree->m_dimension); + + memcpy(m_ptrMBR[cChild]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pVLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pVHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(&(m_ptrMBR[cChild]->m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + m_ptrMBR[cChild]->m_endTime = std::numeric_limits<double>::max(); + + memcpy(&(m_pIdentifier[cChild]), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(&(m_pDataLength[cChild]), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + m_totalDataLength += m_pDataLength[cChild]; + m_pData[cChild] = new byte[m_pDataLength[cChild]]; + memcpy(m_pData[cChild], ptr, m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + else + { + m_pData[cChild] = 0; + } + + //m_nodeMBR.combineRegion(*(m_ptrMBR[cChild])); + } + + memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pVLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pVHigh, ptr, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +void Node::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + + *data = new byte[len]; + byte* ptr = *data; + + uint32_t nodeType; + + if (m_level == 0) nodeType = PersistentLeaf; + else nodeType = PersistentIndex; + + memcpy(ptr, &nodeType, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_level, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_children, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &(m_nodeMBR.m_startTime), sizeof(double)); + ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + memcpy(ptr, m_ptrMBR[cChild]->m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pVLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pVHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, &(m_ptrMBR[cChild]->m_startTime), sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, &(m_pIdentifier[cChild]), sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(ptr, &(m_pDataLength[cChild]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + memcpy(ptr, m_pData[cChild], m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + } + + // store the node MBR for efficiency. This increases the node size a little bit. + memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pVLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pVHigh, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); + + assert(len == (ptr - *data) + m_pTree->m_dimension * sizeof(double)); +} + +// +// SpatialIndex::IEntry interface +// +id_type Node::getIdentifier() const +{ + return m_identifier; +} + +void Node::getShape(IShape** out) const +{ + *out = new MovingRegion(m_nodeMBR); +} + +// +// SpatialIndex::INode interface +// +uint32_t Node::getChildrenCount() const +{ + return m_children; +} + +id_type Node::getChildIdentifier(uint32_t index) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + return m_pIdentifier[index]; +} + +void Node::getChildShape(uint32_t index, IShape** out) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + *out = new MovingRegion(*(m_ptrMBR[index])); +} + +void Node::getChildData(uint32_t index, uint32_t& length, byte** data) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + if (m_pData[index] == NULL) + { + length = 0; + data = NULL; + } + else + { + length = m_pDataLength[index]; + *data = m_pData[index]; + } +} + +uint32_t Node::getLevel() const +{ + return m_level; +} + +bool Node::isLeaf() const +{ + return (m_level == 0); +} + +bool Node::isIndex() const +{ + return (m_level != 0); +} + +// +// Internal +// + +Node::Node() : + m_pTree(0), + m_level(0), + m_identifier(-1), + m_children(0), + m_capacity(0), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ +} + +Node::Node(SpatialIndex::TPRTree::TPRTree* pTree, id_type id, uint32_t level, uint32_t capacity) : + m_pTree(pTree), + m_level(level), + m_identifier(id), + m_children(0), + m_capacity(capacity), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ + m_nodeMBR.makeInfinite(m_pTree->m_dimension); + + try + { + m_pDataLength = new uint32_t[m_capacity + 1]; + m_pData = new byte*[m_capacity + 1]; + m_ptrMBR = new MovingRegionPtr[m_capacity + 1]; + m_pIdentifier = new id_type[m_capacity + 1]; + } + catch (...) + { + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + throw; + } +} + +Node::~Node() +{ + if (m_pData != 0) + { + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_pData[cChild] != 0) delete[] m_pData[cChild]; + } + + delete[] m_pData; + } + + delete[] m_pDataLength; + delete[] m_ptrMBR; + delete[] m_pIdentifier; +} + +Node& Node::operator=(const Node& n) +{ + throw Tools::IllegalStateException("Node::operator =: This should never be called."); +} + +bool Node::insertEntry(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id) +{ + assert(m_children < m_capacity); + + bool bAdjusted = false; + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + m_totalDataLength += dataLength; + ++m_children; + + if (m_nodeMBR.m_startTime != m_pTree->m_currentTime) + { + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + + bAdjusted = true; + } + else if ( + //m_nodeMBR.m_pLow[0] != std::numeric_limits<double>::max() && + ! m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, mbr)) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + double l = m_nodeMBR.getExtrapolatedLow(cDim, m_pTree->m_currentTime); + double rl = mbr.getExtrapolatedLow(cDim, m_pTree->m_currentTime); + if (rl <= l) + { + m_nodeMBR.m_pLow[cDim] = rl - 2.0 * std::numeric_limits<double>::epsilon(); + } + + double h = m_nodeMBR.getExtrapolatedHigh(cDim, m_pTree->m_currentTime); + double rh = mbr.getExtrapolatedHigh(cDim, m_pTree->m_currentTime); + if (rh >= h) + { + m_nodeMBR.m_pHigh[cDim] = rh + 2.0 * std::numeric_limits<double>::epsilon(); + } + + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], mbr.m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], mbr.m_pVHigh[cDim]); + } + + bAdjusted = true; + } + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_nodeMBR.m_startTime, *(m_ptrMBR[cChild]))); + } +#endif + + return true; +} + +void Node::deleteEntry(uint32_t index) +{ + assert(index >= 0 && index < m_children); + + // cache it, since I might need it for "touches" later. + MovingRegionPtr ptrR = m_ptrMBR[index]; + + m_totalDataLength -= m_pDataLength[index]; + if (m_pData[index] != 0) delete[] m_pData[index]; + + if (m_children > 1 && index != m_children - 1) + { + m_pDataLength[index] = m_pDataLength[m_children - 1]; + m_pData[index] = m_pData[m_children - 1]; + m_ptrMBR[index] = m_ptrMBR[m_children - 1]; + m_pIdentifier[index] = m_pIdentifier[m_children - 1]; + } + + --m_children; + + // WARNING: index has now changed. Do not use it below here. + + if (m_children == 0) + { + m_nodeMBR = m_pTree->m_infiniteRegion; + } + else //if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesRegion(*ptrR)) + { + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, *(m_ptrMBR[cChild])) == true); + } +#endif + } +} + +bool Node::insertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + if (m_children < m_capacity) + { + bool bNeedToAdjust = insertEntry(dataLength, pData, mbr, id); + m_pTree->writeNode(this); + + if (bNeedToAdjust && ! pathBuffer.empty()) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } + + return bNeedToAdjust; + } + else if (false && m_pTree->m_treeVariant == TPRV_RSTAR && ! pathBuffer.empty() && overflowTable[m_level] == 0) + { + overflowTable[m_level] = 1; + + std::vector<uint32_t> vReinsert, vKeep; + reinsertData(dataLength, pData, mbr, id, vReinsert, vKeep); + + uint32_t lReinsert = static_cast<uint32_t>(vReinsert.size()); + uint32_t lKeep = static_cast<uint32_t>(vKeep.size()); + + byte** reinsertdata = 0; + MovingRegionPtr* reinsertmbr = 0; + id_type* reinsertid = 0; + uint32_t* reinsertlen = 0; + byte** keepdata = 0; + MovingRegionPtr* keepmbr = 0; + id_type* keepid = 0; + uint32_t* keeplen = 0; + + try + { + reinsertdata = new byte*[lReinsert]; + reinsertmbr = new MovingRegionPtr[lReinsert]; + reinsertid = new id_type[lReinsert]; + reinsertlen = new uint32_t[lReinsert]; + + keepdata = new byte*[m_capacity + 1]; + keepmbr = new MovingRegionPtr[m_capacity + 1]; + keepid = new id_type[m_capacity + 1]; + keeplen = new uint32_t[m_capacity + 1]; + } + catch (...) + { + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + delete[] keepdata; + delete[] keepmbr; + delete[] keepid; + delete[] keeplen; + throw; + } + + uint32_t cIndex; + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + reinsertlen[cIndex] = m_pDataLength[vReinsert[cIndex]]; + reinsertdata[cIndex] = m_pData[vReinsert[cIndex]]; + reinsertmbr[cIndex] = m_ptrMBR[vReinsert[cIndex]]; + reinsertid[cIndex] = m_pIdentifier[vReinsert[cIndex]]; + } + + for (cIndex = 0; cIndex < lKeep; ++cIndex) + { + keeplen[cIndex] = m_pDataLength[vKeep[cIndex]]; + keepdata[cIndex] = m_pData[vKeep[cIndex]]; + keepmbr[cIndex] = m_ptrMBR[vKeep[cIndex]]; + keepid[cIndex] = m_pIdentifier[vKeep[cIndex]]; + } + + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + + m_pDataLength = keeplen; + m_pData = keepdata; + m_ptrMBR = keepmbr; + m_pIdentifier = keepid; + m_children = lKeep; + m_totalDataLength = 0; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) m_totalDataLength += m_pDataLength[cChild]; + + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_nodeMBR.m_startTime, *(m_ptrMBR[cChild]))); + } +#endif + + m_pTree->writeNode(this); + + // Divertion from R*-Tree algorithm here. First adjust + // the path to the root, then start reinserts, to avoid complicated handling + // of changes to the same node from multiple insertions. + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + m_pTree->insertData_impl( + reinsertlen[cIndex], reinsertdata[cIndex], + *(reinsertmbr[cIndex]), reinsertid[cIndex], + m_level, overflowTable); + } + + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + + return true; + } + else + { + NodePtr n; + NodePtr nn; + split(dataLength, pData, mbr, id, n, nn); + + if (pathBuffer.empty()) + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = -1; + nn->m_identifier = -1; + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + assert(n->m_nodeMBR.containsRegionAfterTime(n->m_nodeMBR.m_startTime, *(n->m_ptrMBR[cChild])) == true); + } + for (uint32_t cChild = 0; cChild < nn->m_children; ++cChild) + { + assert(nn->m_nodeMBR.containsRegionAfterTime(nn->m_nodeMBR.m_startTime, *(nn->m_ptrMBR[cChild])) == true); + } +#endif + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + NodePtr ptrR = m_pTree->m_indexPool.acquire(); + if (ptrR.get() == 0) + { + ptrR = NodePtr(new Index(m_pTree, m_pTree->m_rootID, m_level + 1), &(m_pTree->m_indexPool)); + } + else + { + //ptrR->m_pTree = m_pTree; + ptrR->m_identifier = m_pTree->m_rootID; + ptrR->m_level = m_level + 1; + ptrR->m_nodeMBR = m_pTree->m_infiniteRegion; + } + + ptrR->insertEntry(0, 0, n->m_nodeMBR, n->m_identifier); + ptrR->insertEntry(0, 0, nn->m_nodeMBR, nn->m_identifier); + + m_pTree->writeNode(ptrR.get()); + + m_pTree->m_stats.m_nodesInLevel[m_level] = 2; + m_pTree->m_stats.m_nodesInLevel.push_back(1); + m_pTree->m_stats.m_treeHeight = m_level + 2; + } + else + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = m_identifier; + nn->m_identifier = -1; + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + assert(n->m_nodeMBR.containsRegionAfterTime(n->m_nodeMBR.m_startTime, *(n->m_ptrMBR[cChild])) == true); + } + for (uint32_t cChild = 0; cChild < nn->m_children; ++cChild) + { + assert(nn->m_nodeMBR.containsRegionAfterTime(nn->m_nodeMBR.m_startTime, *(nn->m_ptrMBR[cChild])) == true); + } +#endif + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(n.get(), nn.get(), pathBuffer, overflowTable); + } + + return true; + } +} + +void Node::reinsertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep) +{ + ReinsertEntry** v = new ReinsertEntry*[m_capacity + 1]; + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + for (uint32_t cChild = 0; cChild < m_capacity + 1; ++cChild) + { + try + { + v[cChild] = new ReinsertEntry(cChild, 0.0); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete v[i]; + delete[] v; + throw; + } + + v[cChild]->m_dist = m_nodeMBR.getCenterDistanceInTime(ivT, *(m_ptrMBR[cChild])); + } + + // sort by increasing order of distances. + ::qsort(v, m_capacity + 1, sizeof(ReinsertEntry*), ReinsertEntry::compareReinsertEntry); + + uint32_t cReinsert = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_reinsertFactor)); + + uint32_t cCount; + + for (cCount = 0; cCount < cReinsert; ++cCount) + { + reinsert.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + for (cCount = cReinsert; cCount < m_capacity + 1; ++cCount) + { + keep.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + delete[] v; +} + +/* +void Node::rtreeSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + uint32_t cChild; + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + // use this mask array for marking visited entries. + byte* mask = new byte[m_capacity + 1]; + bzero(mask, m_capacity + 1); + + // insert new data in the node for easier manipulation. Data arrays are always + // by one larger than node capacity. + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + + // initialize each group with the seed entries. + uint32_t seed1, seed2; + pickSeeds(seed1, seed2); + + group1.push_back(seed1); + group2.push_back(seed2); + + mask[seed1] = 1; + mask[seed2] = 1; + + // find MBR of each group. + RegionPtr mbr1 = m_pTree->m_regionPool.acquire(); + *mbr1 = *(m_ptrMBR[seed1]); + RegionPtr mbr2 = m_pTree->m_regionPool.acquire(); + *mbr2 = *(m_ptrMBR[seed2]); + + // count how many entries are left unchecked (exclude the seeds here.) + uint32_t cRemaining = m_capacity + 1 - 2; + + while (cRemaining > 0) + { + if (minimumLoad - group1.size() == cRemaining) + { + // all remaining entries must be assigned to group1 to comply with minimun load requirement. + for (cChild = 0; cChild < m_capacity + 1; ++cChild) + { + if (mask[cChild] == 0) + { + group1.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else if (minimumLoad - group2.size() == cRemaining) + { + // all remaining entries must be assigned to group2 to comply with minimun load requirement. + for (cChild = 0; cChild < m_capacity + 1; ++cChild) + { + if (mask[cChild] == 0) + { + group2.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else + { + // For all remaining entries compute the difference of the cost of grouping an + // entry in either group. When done, choose the entry that yielded the maximum + // difference. In case of linear split, select any entry (e.g. the first one.) + uint32_t sel; + double md1 = 0.0, md2 = 0.0; + double m = -std::numeric_limits<double>::max(); + double d1, d2, d; + double a1 = mbr1->getArea(); + double a2 = mbr2->getArea(); + + RegionPtr a = m_pTree->m_regionPool.acquire(); + RegionPtr b = m_pTree->m_regionPool.acquire(); + + for (cChild = 0; cChild < m_capacity + 1; ++cChild) + { + if (mask[cChild] == 0) + { + mbr1->getCombinedRegion(*a, *(m_ptrMBR[cChild])); + d1 = a->getArea() - a1; + mbr2->getCombinedRegion(*b, *(m_ptrMBR[cChild])); + d2 = b->getArea() - a2; + d = std::abs(d1 - d2); + + if (d > m) + { + m = d; + md1 = d1; md2 = d2; + sel = cChild; + if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break; + } + } + } + + // determine the group where we should add the new entry. + int32_t group = -1; + + if (md1 < md2) + { + group1.push_back(sel); + group = 1; + } + else if (md2 < md1) + { + group2.push_back(sel); + group = 2; + } + else if (a1 < a2) + { + group1.push_back(sel); + group = 1; + } + else if (a2 < a1) + { + group2.push_back(sel); + group = 2; + } + else if (group1.size() < group2.size()) + { + group1.push_back(sel); + group = 1; + } + else if (group2.size() < group1.size()) + { + group2.push_back(sel); + group = 2; + } + else + { + group1.push_back(sel); + group = 1; + } + mask[sel] = 1; + --cRemaining; + if (group == 1) + { + mbr1->combineRegion(*(m_ptrMBR[sel])); + } + else + { + mbr2->combineRegion(*(m_ptrMBR[sel])); + } + } + } + + delete[] mask; +} +*/ + +void Node::rstarSplit(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + RstarSplitEntry** dataLow = 0; + RstarSplitEntry** dataHigh = 0; + RstarSplitEntry** dataVLow = 0; + RstarSplitEntry** dataVHigh = 0; + + try + { + dataLow = new RstarSplitEntry*[m_capacity + 1]; + dataHigh = new RstarSplitEntry*[m_capacity + 1]; + dataVLow = new RstarSplitEntry*[m_capacity + 1]; + dataVHigh = new RstarSplitEntry*[m_capacity + 1]; + } + catch (...) + { + delete[] dataLow; + delete[] dataHigh; + delete[] dataVLow; + delete[] dataVHigh; + throw; + } + + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + + uint32_t nodeSPF = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_splitDistributionFactor)); + uint32_t splitDistribution = (m_capacity + 1) - (2 * nodeSPF) + 2; + + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + uint32_t cChild = 0, cDim, cIndex; + + for (cChild = 0; cChild <= m_capacity; ++cChild) + { + try + { + dataLow[cChild] = new RstarSplitEntry(m_ptrMBR[cChild].get(), cChild, 0); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete dataLow[i]; + delete[] dataLow; + delete[] dataHigh; + throw; + } + + dataHigh[cChild] = dataLow[cChild]; + dataVLow[cChild] = dataLow[cChild]; + dataVHigh[cChild] = dataLow[cChild]; + } + + double minimumMargin = std::numeric_limits<double>::max(); + uint32_t splitAxis = std::numeric_limits<uint32_t>::max(); + uint32_t sortOrder = std::numeric_limits<uint32_t>::max(); + + // chooseSplitAxis. + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow); + ::qsort(dataHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh); + ::qsort(dataVLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVLow); + ::qsort(dataVHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVHigh); + + // calculate sum of margins and overlap for all distributions. + double marginl = 0.0; + double marginh = 0.0; + double marginvl = 0.0; + double marginvh = 0.0; + + MovingRegion bbl1, bbl2, bbh1, bbh2; + MovingRegion bbvl1, bbvl2, bbvh1, bbvh2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bbl1 = *(dataLow[0]->m_pRegion); + bbh1 = *(dataHigh[0]->m_pRegion); + bbvl1 = *(dataVLow[0]->m_pRegion); + bbvh1 = *(dataVHigh[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bbl1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + bbh1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataHigh[cIndex]->m_pRegion)); + bbvl1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVLow[cIndex]->m_pRegion)); + bbvh1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVHigh[cIndex]->m_pRegion)); + } + + bbl2 = *(dataLow[l]->m_pRegion); + bbh2 = *(dataHigh[l]->m_pRegion); + bbvl2 = *(dataVLow[l]->m_pRegion); + bbvh2 = *(dataVHigh[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bbl2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + bbh2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataHigh[cIndex]->m_pRegion)); + bbvl2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVLow[cIndex]->m_pRegion)); + bbvh2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVHigh[cIndex]->m_pRegion)); + } + + marginl += bbl1.getProjectedSurfaceAreaInTime(ivT) + bbl2.getProjectedSurfaceAreaInTime(ivT); + marginh += bbh1.getProjectedSurfaceAreaInTime(ivT) + bbh2.getProjectedSurfaceAreaInTime(ivT); + marginvl += bbvl1.getProjectedSurfaceAreaInTime(ivT) + bbvl2.getProjectedSurfaceAreaInTime(ivT); + marginvh += bbvh1.getProjectedSurfaceAreaInTime(ivT) + bbvh2.getProjectedSurfaceAreaInTime(ivT); + } // for (cChild) + + double margin = std::min(std::min(marginl, marginh), std::min(marginvl, marginvh)); + + // keep minimum margin as split axis. + if (margin < minimumMargin) + { + minimumMargin = margin; + splitAxis = cDim; + if (marginl < marginh && marginl < marginvl && marginl < marginvh) sortOrder = 0; + else if (marginh < marginl && marginh < marginvl && marginh < marginvh) sortOrder = 1; + else if (marginvl < marginl && marginvl < marginh && marginvl < marginvh) sortOrder = 2; + else if (marginvh < marginl && marginvh < marginh && marginvh < marginvl) sortOrder = 3; + } + + // increase the dimension according to which the data entries should be sorted. + for (cChild = 0; cChild <= m_capacity; ++cChild) + { + dataLow[cChild]->m_sortDim = cDim + 1; + } + } // for (cDim) + + for (cChild = 0; cChild <= m_capacity; ++cChild) + { + dataLow[cChild]->m_sortDim = splitAxis; + } + + if (sortOrder == 0) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow); + else if (sortOrder == 1) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh); + else if (sortOrder == 2) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVLow); + else if (sortOrder == 3) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVHigh); + + double ma = std::numeric_limits<double>::max(); + double mo = std::numeric_limits<double>::max(); + uint32_t splitPoint = std::numeric_limits<uint32_t>::max(); + + MovingRegion bb1, bb2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bb1 = *(dataLow[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bb1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + } + + bb2 = *(dataLow[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bb2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + } + + double o = bb1.getIntersectingAreaInTime(ivT, bb2); + + if (o < mo) + { + splitPoint = cChild; + mo = o; + ma = bb1.getAreaInTime(ivT) + bb2.getAreaInTime(ivT); + } + else if (o == mo) + { + double a = bb1.getAreaInTime(ivT) + bb2.getAreaInTime(ivT); + + if (a < ma) + { + splitPoint = cChild; + ma = a; + } + } + } // for (cChild) + + uint32_t l1 = nodeSPF - 1 + splitPoint; + + for (cIndex = 0; cIndex < l1; ++cIndex) + { + group1.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + for (cIndex = l1; cIndex <= m_capacity; ++cIndex) + { + group2.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + delete[] dataLow; + delete[] dataHigh; + delete[] dataVLow; + delete[] dataVHigh; +} + +/* +void Node::pickSeeds(uint32_t& index1, uint32_t& index2) +{ + double separation = -std::numeric_limits<double>::max(); + double inefficiency = -std::numeric_limits<double>::max(); + uint32_t cDim, cChild, cIndex; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_RSTAR: + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + double leastLower = m_ptrMBR[0]->m_pLow[cDim]; + double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim]; + uint32_t greatestLower = 0; + uint32_t leastUpper = 0; + double width; + + for (cChild = 1; cChild <= m_capacity; ++cChild) + { + if (m_ptrMBR[cChild]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = cChild; + if (m_ptrMBR[cChild]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = cChild; + + leastLower = std::min(m_ptrMBR[cChild]->m_pLow[cDim], leastLower); + greatestUpper = std::max(m_ptrMBR[cChild]->m_pHigh[cDim], greatestUpper); + } + + width = greatestUpper - leastLower; + if (width <= 0) width = 1; + + double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width; + + if (f > separation) + { + index1 = leastUpper; + index2 = greatestLower; + separation = f; + } + } // for (cDim) + + if (index1 == index2) + { + if (index2 == 0) ++index2; + else --index2; + } + + break; + case RV_QUADRATIC: + // for each pair of Regions (account for overflow Region too!) + for (cChild = 0; cChild < m_capacity; ++cChild) + { + double a = m_ptrMBR[cChild]->getArea(); + + for (cIndex = cChild + 1; cIndex <= m_capacity; ++cIndex) + { + // get the combined MBR of those two entries. + Region r; + m_ptrMBR[cChild]->getCombinedRegion(r, *(m_ptrMBR[cIndex])); + + // find the inefficiency of grouping these entries together. + double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea(); + + if (d > inefficiency) + { + inefficiency = d; + index1 = cChild; + index2 = cIndex; + } + } // for (cIndex) + } // for (cChild) + + break; + default: + throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported."); + } +} +*/ + +void Node::condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis) +{ + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + if (pathBuffer.empty()) + { + // eliminate root if it has only one child. + if (m_level != 0 && m_children == 1) + { + NodePtr ptrN = m_pTree->readNode(m_pIdentifier[0]); + m_pTree->deleteNode(ptrN.get()); + ptrN->m_identifier = m_pTree->m_rootID; + m_pTree->writeNode(ptrN.get()); + + m_pTree->m_stats.m_nodesInLevel.pop_back(); + m_pTree->m_stats.m_treeHeight -= 1; + // HACK: pending deleteNode for deleted child will decrease nodesInLevel, later on. + m_pTree->m_stats.m_nodesInLevel[m_pTree->m_stats.m_treeHeight - 1] = 2; + } + } + else + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrParent = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrParent.get()); + + // find the entry in the parent, that points to this node. + uint32_t child; + + for (child = 0; child != p->m_children; ++child) + { + if (p->m_pIdentifier[child] == m_identifier) break; + } + + if (m_children < minimumLoad) + { + // used space less than the minimum + // 1. eliminate node entry from the parent. deleteEntry will fix the parent's MBR. + p->deleteEntry(child); + // 2. add this node to the stack in order to reinsert its entries. + toReinsert.push(ptrThis); + } + else + { + // adjust the entry in 'p' to contain the new bounding region of this node. + *(p->m_ptrMBR[child]) = m_nodeMBR; + + // global recalculation necessary since the MBR can only shrink in size, + // due to data removal. + //if (m_pTree->m_bTightMBRs) + //{ + + p->m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < p->m_nodeMBR.m_dimension; ++cDim) + { + p->m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + p->m_nodeMBR.m_pLow[cDim] = std::min(p->m_nodeMBR.m_pLow[cDim], p->m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_pTree->m_currentTime)); + p->m_nodeMBR.m_pHigh[cDim] = std::max(p->m_nodeMBR.m_pHigh[cDim], p->m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_pTree->m_currentTime)); + p->m_nodeMBR.m_pVLow[cDim] = std::min(p->m_nodeMBR.m_pVLow[cDim], p->m_ptrMBR[cChild]->m_pVLow[cDim]); + p->m_nodeMBR.m_pVHigh[cDim] = std::max(p->m_nodeMBR.m_pVHigh[cDim], p->m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + p->m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + p->m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + //} + } + + // write parent node back to storage. + m_pTree->writeNode(p); + + p->condenseTree(toReinsert, pathBuffer, ptrParent); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Node.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Node.h.svn-base new file mode 100644 index 000000000..6cf5d98a0 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Node.h.svn-base @@ -0,0 +1,200 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class TPRTree; + class Leaf; + class Index; + class Node; + + typedef Tools::PoolPointer<Node> NodePtr; + + class Node : public SpatialIndex::INode + { + public: + virtual ~Node(); + + // + // Tools::IObject interface + // + virtual Tools::IObject* clone(); + + // + // Tools::ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // SpatialIndex::IEntry interface + // + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + + // + // SpatialIndex::INode interface + // + virtual uint32_t getChildrenCount() const; + virtual id_type getChildIdentifier(uint32_t index) const; + virtual void getChildShape(uint32_t index, IShape** out) const; + virtual void getChildData(uint32_t index, uint32_t& length, byte** data) const; + virtual uint32_t getLevel() const; + virtual bool isIndex() const; + virtual bool isLeaf() const; + + private: + Node(); + Node(TPRTree* pTree, id_type id, uint32_t level, uint32_t capacity); + + virtual Node& operator=(const Node&); + + virtual bool insertEntry(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id); + virtual void deleteEntry(uint32_t index); + + virtual bool insertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable); + virtual void reinsertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep); + + virtual void rstarSplit(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2); + + virtual void condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis); + + virtual NodePtr chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) = 0; + + virtual void split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& left, NodePtr& right) = 0; + + TPRTree* m_pTree; + // Parent of all nodes. + + uint32_t m_level; + // The level of the node in the tree. + // Leaves are always at level 0. + + id_type m_identifier; + // The unique ID of this node. + + uint32_t m_children; + // The number of children pointed by this node. + + uint32_t m_capacity; + // Specifies the node capacity. + + MovingRegion m_nodeMBR; + // The minimum bounding region enclosing all data contained in the node. + + byte** m_pData; + // The data stored in the node. + + MovingRegionPtr* m_ptrMBR; + // The corresponding data MBRs. + + id_type* m_pIdentifier; + // The corresponding data identifiers. + + uint32_t* m_pDataLength; + + uint32_t m_totalDataLength; + + class RstarSplitEntry + { + public: + MovingRegion* m_pRegion; + uint32_t m_index; + uint32_t m_sortDim; + + RstarSplitEntry(MovingRegion* pr, uint32_t index, uint32_t dimension) + : m_pRegion(pr), m_index(index), m_sortDim(dimension) {} + + static int compareLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] < pe2->m_pRegion->m_pLow[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] > pe2->m_pRegion->m_pLow[pe1->m_sortDim]) return 1; + return 0; + } + + static int compareHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pHigh[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pHigh[pe1->m_sortDim]) return 1; + return 0; + } + + static int compareVLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pVLow[pe1->m_sortDim] < pe2->m_pRegion->m_pVLow[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pVLow[pe1->m_sortDim] > pe2->m_pRegion->m_pVLow[pe1->m_sortDim]) return 1; + return 0; + } + + static int compareVHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pVHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pVHigh[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pVHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pVHigh[pe1->m_sortDim]) return 1; + return 0; + } + }; // RstarSplitEntry + + class ReinsertEntry + { + public: + uint32_t m_index; + double m_dist; + + ReinsertEntry(uint32_t index, double dist) : m_index(index), m_dist(dist) {} + + static int compareReinsertEntry(const void* pv1, const void* pv2) + { + ReinsertEntry* pe1 = * (ReinsertEntry**) pv1; + ReinsertEntry* pe2 = * (ReinsertEntry**) pv2; + + if (pe1->m_dist < pe2->m_dist) return -1; + if (pe1->m_dist > pe2->m_dist) return 1; + return 0; + } + }; // ReinsertEntry + + // Needed to access protected members without having to cast from Node. + // It is more efficient than using member functions to access protected members. + friend class TPRTree; + friend class Leaf; + friend class Index; + friend class Tools::PointerPool<Node>; + }; // Node + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/PointerPoolNode.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/PointerPoolNode.h.svn-base new file mode 100644 index 000000000..8c026fbe3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/PointerPoolNode.h.svn-base @@ -0,0 +1,133 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Node.h" + +namespace Tools +{ + template<> class PointerPool<TPRTree::Node> + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + TPRTree::Node* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<TPRTree::Node> acquire() + { + if (! m_pool.empty()) + { + TPRTree::Node* p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + ++m_hits; + #endif + + return PoolPointer<TPRTree::Node>(p, this); + } + #ifndef NDEBUG + else + { + // fixme: well sort of... + ++m_pointerCount; + ++m_misses; + } + #endif + + return PoolPointer<TPRTree::Node>(); + } + + void release(TPRTree::Node* p) + { + if (p != 0) + { + if (m_pool.size() < m_capacity) + { + if (p->m_pData != 0) + { + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + if (p->m_pData[cChild] != 0) delete[] p->m_pData[cChild]; + } + } + + p->m_level = 0; + p->m_identifier = -1; + p->m_children = 0; + p->m_totalDataLength = 0; + + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + protected: + uint32_t m_capacity; + std::stack<TPRTree::Node*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Statistics.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Statistics.cc.svn-base new file mode 100644 index 000000000..d2031d4db --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Statistics.cc.svn-base @@ -0,0 +1,171 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Statistics.h" + +using namespace SpatialIndex::TPRTree; + +Statistics::Statistics() +{ + reset(); +} + +Statistics::Statistics(const Statistics& s) +{ + m_reads = s.m_reads; + m_writes = s.m_writes; + m_splits = s.m_splits; + m_hits = s.m_hits; + m_misses = s.m_misses; + m_nodes = s.m_nodes; + m_adjustments = s.m_adjustments; + m_queryResults = s.m_queryResults; + m_data = s.m_data; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; +} + +Statistics::~Statistics() +{ +} + +Statistics& Statistics::operator=(const Statistics& s) +{ + if (this != &s) + { + m_reads = s.m_reads; + m_writes = s.m_writes; + m_splits = s.m_splits; + m_hits = s.m_hits; + m_misses = s.m_misses; + m_nodes = s.m_nodes; + m_adjustments = s.m_adjustments; + m_queryResults = s.m_queryResults; + m_data = s.m_data; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; + } + + return *this; +} + +uint64_t Statistics::getReads() const +{ + return m_reads; +} + +uint64_t Statistics::getWrites() const +{ + return m_writes; +} + +uint32_t Statistics::getNumberOfNodes() const +{ + return m_nodes; +} + +uint64_t Statistics::getNumberOfData() const +{ + return m_data; +} + +uint64_t Statistics::getSplits() const +{ + return m_splits; +} + +uint64_t Statistics::getHits() const +{ + return m_hits; +} + +uint64_t Statistics::getMisses() const +{ + return m_misses; +} + +uint64_t Statistics::getAdjustments() const +{ + return m_adjustments; +} + +uint64_t Statistics::getQueryResults() const +{ + return m_queryResults; +} + +uint32_t Statistics::getTreeHeight() const +{ + return m_treeHeight; +} + +uint32_t Statistics::getNumberOfNodesInLevel(uint32_t l) const +{ + uint32_t cNodes; + try + { + cNodes = m_nodesInLevel.at(l); + } + catch (...) + { + throw Tools::IndexOutOfBoundsException(l); + } + + return cNodes; +} + +void Statistics::reset() +{ + m_reads = 0; + m_writes = 0; + m_splits = 0; + m_hits = 0; + m_misses = 0; + m_nodes = 0; + m_adjustments = 0; + m_queryResults = 0; + m_data = 0; + m_treeHeight = 0; + m_nodesInLevel.clear(); +} + +std::ostream& SpatialIndex::TPRTree::operator<<(std::ostream& os, const Statistics& s) +{ + os << "Reads: " << s.m_reads << std::endl + << "Writes: " << s.m_writes << std::endl + << "Hits: " << s.m_hits << std::endl + << "Misses: " << s.m_misses << std::endl + << "Tree height: " << s.m_treeHeight << std::endl + << "Number of data: " << s.m_data << std::endl + << "Number of nodes: " << s.m_nodes << std::endl; + + for (uint32_t cLevel = 0; cLevel < s.m_treeHeight; ++cLevel) + { + os << "Level " << cLevel << " pages: " << s.m_nodesInLevel[cLevel] << std::endl; + } + + os << "Splits: " << s.m_splits << std::endl + << "Adjustments: " << s.m_adjustments << std::endl + << "Query results: " << s.m_queryResults << std::endl; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Statistics.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Statistics.h.svn-base new file mode 100644 index 000000000..44b707c30 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/Statistics.h.svn-base @@ -0,0 +1,93 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class TPRTree; + class Node; + class Leaf; + class Index; + + class Statistics : public SpatialIndex::IStatistics + { + public: + Statistics(); + Statistics(const Statistics&); + virtual ~Statistics(); + Statistics& operator=(const Statistics&); + + // + // IStatistics interface + // + virtual uint64_t getReads() const; + virtual uint64_t getWrites() const; + virtual uint32_t getNumberOfNodes() const; + virtual uint64_t getNumberOfData() const; + + virtual uint64_t getSplits() const; + virtual uint64_t getHits() const; + virtual uint64_t getMisses() const; + virtual uint64_t getAdjustments() const; + virtual uint64_t getQueryResults() const; + virtual uint32_t getTreeHeight() const; + virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const; + + private: + void reset(); + + uint64_t m_reads; + + uint64_t m_writes; + + uint64_t m_splits; + + uint64_t m_hits; + + uint64_t m_misses; + + uint32_t m_nodes; + + uint64_t m_adjustments; + + uint64_t m_queryResults; + + uint64_t m_data; + + uint32_t m_treeHeight; + + std::vector<uint32_t> m_nodesInLevel; + + friend class TPRTree; + friend class Node; + friend class Index; + friend class Leaf; + friend class BulkLoader; + + friend std::ostream& operator<<(std::ostream& os, const Statistics& s); + }; // Statistics + + std::ostream& operator<<(std::ostream& os, const Statistics& s); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/TPRTree.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/TPRTree.cc.svn-base new file mode 100644 index 000000000..16b8f9c54 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/TPRTree.cc.svn-base @@ -0,0 +1,1352 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" +#include "TPRTree.h" + +#include <cstring> + +using namespace SpatialIndex::TPRTree; + +SpatialIndex::TPRTree::Data::Data(uint32_t len, byte* pData, MovingRegion& r, id_type id) + : m_id(id), m_region(r), m_pData(0), m_dataLength(len) +{ + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, pData, m_dataLength); + } +} + +SpatialIndex::TPRTree::Data::~Data() +{ + delete[] m_pData; +} + +SpatialIndex::TPRTree::Data* SpatialIndex::TPRTree::Data::clone() +{ + return new Data(m_dataLength, m_pData, m_region, m_id); +} + +SpatialIndex::id_type SpatialIndex::TPRTree::Data::getIdentifier() const +{ + return m_id; +} + +void SpatialIndex::TPRTree::Data::getShape(IShape** out) const +{ + *out = new MovingRegion(m_region); +} + +void SpatialIndex::TPRTree::Data::getData(uint32_t& len, byte** data) const +{ + len = m_dataLength; + *data = 0; + + if (m_dataLength > 0) + { + *data = new byte[m_dataLength]; + memcpy(*data, m_pData, m_dataLength); + } +} + +uint32_t SpatialIndex::TPRTree::Data::getByteArraySize() +{ + return + sizeof(id_type) + + sizeof(uint32_t) + + m_dataLength + + m_region.getByteArraySize(); +} + +void SpatialIndex::TPRTree::Data::loadFromByteArray(const byte* ptr) +{ + memcpy(&m_id, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + delete[] m_pData; + m_pData = 0; + + memcpy(&m_dataLength, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, ptr, m_dataLength); + ptr += m_dataLength; + } + + m_region.loadFromByteArray(ptr); +} + +void SpatialIndex::TPRTree::Data::storeToByteArray(byte** data, uint32_t& len) +{ + // it is thread safe this way. + uint32_t regionsize; + byte* regiondata = 0; + m_region.storeToByteArray(®iondata, regionsize); + + len = sizeof(id_type) + sizeof(uint32_t) + m_dataLength + regionsize; + + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_id, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_dataLength, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + memcpy(ptr, m_pData, m_dataLength); + ptr += m_dataLength; + } + + memcpy(ptr, regiondata, regionsize); + delete[] regiondata; + // ptr += regionsize; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::TPRTree::returnTPRTree(SpatialIndex::IStorageManager& sm, Tools::PropertySet& ps) +{ + SpatialIndex::ISpatialIndex* si = new SpatialIndex::TPRTree::TPRTree(sm, ps); + return si; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::TPRTree::createNewTPRTree( + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + TPRTreeVariant rv, + double horizon, + id_type& indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = fillFactor; + ps.setProperty("FillFactor", var); + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = horizon; + ps.setProperty("Horizon", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = indexCapacity; + ps.setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = leafCapacity; + ps.setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = dimension; + ps.setProperty("Dimension", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = rv; + ps.setProperty("TreeVariant", var); + + ISpatialIndex* ret = returnTPRTree(sm, ps); + + var.m_varType = Tools::VT_LONGLONG; + var = ps.getProperty("IndexIdentifier"); + indexIdentifier = var.m_val.llVal; + + return ret; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::TPRTree::loadTPRTree(IStorageManager& sm, id_type indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = indexIdentifier; + ps.setProperty("IndexIdentifier", var); + + return returnTPRTree(sm, ps); +} + +SpatialIndex::TPRTree::TPRTree::TPRTree(IStorageManager& sm, Tools::PropertySet& ps) : + m_pStorageManager(&sm), + m_rootID(StorageManager::NewPage), + m_headerID(StorageManager::NewPage), + m_treeVariant(TPRV_RSTAR), + m_fillFactor(0.7), + m_indexCapacity(100), + m_leafCapacity(100), + m_nearMinimumOverlapFactor(32), + m_splitDistributionFactor(0.4), + m_reinsertFactor(0.3), + m_dimension(2), + m_bTightMBRs(true), + m_currentTime(0.0), + m_horizon(20.0), + m_pointPool(500), + m_regionPool(1000), + m_indexPool(100), + m_leafPool(100) +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + + Tools::Variant var = ps.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType == Tools::VT_LONGLONG) m_headerID = var.m_val.llVal; + else if (var.m_varType == Tools::VT_LONG) m_headerID = var.m_val.lVal; + // for backward compatibility only. + else throw Tools::IllegalArgumentException("TPRTree: Property IndexIdentifier must be Tools::VT_LONGLONG"); + + initOld(ps); + } + else + { + initNew(ps); + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = m_headerID; + ps.setProperty("IndexIdentifier", var); + } +} + +SpatialIndex::TPRTree::TPRTree::~TPRTree() +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_destroy(&m_rwLock); +#endif + + storeHeader(); +} + +// +// ISpatialIndex interface +// + +void SpatialIndex::TPRTree::TPRTree::insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + const IEvolvingShape* es = dynamic_cast<const IEvolvingShape*>(&shape); + if (es == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IEvolvingShape interface."); + const Tools::IInterval *pivI = dynamic_cast<const Tools::IInterval*>(&shape); + if (pivI == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IInterval interface."); + + if (pivI->getLowerBound() < m_currentTime) throw Tools::IllegalArgumentException("insertData: Shape start time is older than tree current time."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("insertData: cannot acquire an exclusive lock"); +#endif + + try + { + Region mbr; + shape.getMBR(mbr); + Region vbr; + es->getVMBR(vbr); + assert(mbr.m_dimension == vbr.m_dimension); + + MovingRegionPtr mr = m_regionPool.acquire(); + mr->makeDimension(mbr.m_dimension); + + memcpy(mr->m_pLow, mbr.m_pLow, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pHigh, mbr.m_pHigh, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVLow, vbr.m_pLow, vbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVHigh, vbr.m_pHigh, vbr.m_dimension * sizeof(double)); + mr->m_startTime = pivI->getLowerBound(); + mr->m_endTime = std::numeric_limits<double>::max(); + + byte* buffer = 0; + + if (len > 0) + { + buffer = new byte[len]; + memcpy(buffer, pData, len); + } + + m_currentTime = mr->m_startTime; + insertData_impl(len, buffer, *mr, id); + // the buffer is stored in the tree. Do not delete here. + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +// shape.m_startTime should be the time when the object was inserted initially. +// shape.m_endTime should be the time of the deletion (current time). +bool SpatialIndex::TPRTree::TPRTree::deleteData(const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + const IEvolvingShape* es = dynamic_cast<const IEvolvingShape*>(&shape); + if (es == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IEvolvingShape interface."); + const Tools::IInterval *pivI = dynamic_cast<const Tools::IInterval*>(&shape); + if (pivI == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IInterval interface."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("deleteData cannot acquire an exclusive lock"); +#endif + + try + { + Region mbr; + shape.getMBR(mbr); + Region vbr; + es->getVMBR(vbr); + assert(mbr.m_dimension == vbr.m_dimension); + + MovingRegionPtr mr = m_regionPool.acquire(); + mr->makeDimension(mbr.m_dimension); + + memcpy(mr->m_pLow, mbr.m_pLow, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pHigh, mbr.m_pHigh, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVLow, vbr.m_pLow, vbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVHigh, vbr.m_pHigh, vbr.m_dimension * sizeof(double)); + mr->m_startTime = pivI->getLowerBound(); + mr->m_endTime = std::numeric_limits<double>::max(); + + m_currentTime = pivI->getUpperBound(); + bool ret = deleteData_impl(*mr, id); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + return ret; + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::containsWhatQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("containsWhatQuery: Shape has the wrong number of dimensions."); + rangeQuery(ContainmentQuery, query, v); +} + +void SpatialIndex::TPRTree::TPRTree::intersectsWithQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("intersectsWithQuery: Shape has the wrong number of dimensions."); + rangeQuery(IntersectionQuery, query, v); +} + +void SpatialIndex::TPRTree::TPRTree::pointLocationQuery(const Point& query, IVisitor& v) +{ + if (query.m_dimension != m_dimension) throw Tools::IllegalArgumentException("pointLocationQuery: Shape has the wrong number of dimensions."); + Region r(query, query); + rangeQuery(IntersectionQuery, r, v); +} + +void SpatialIndex::TPRTree::TPRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) +{ + throw Tools::IllegalStateException("nearestNeighborQuery: not impelmented yet."); +} + +void SpatialIndex::TPRTree::TPRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + NNComparator nnc; + nearestNeighborQuery(k, query, v, nnc); +} + +void SpatialIndex::TPRTree::TPRTree::selfJoinQuery(const IShape& query, IVisitor& v) +{ + throw Tools::IllegalStateException("selfJoinQuery: not impelmented yet."); +} + +void SpatialIndex::TPRTree::TPRTree::queryStrategy(IQueryStrategy& qs) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("queryStrategy: cannot acquire a shared lock"); +#endif + + id_type next = m_rootID; + bool hasNext = true; + + try + { + while (hasNext) + { + NodePtr n = readNode(next); + qs.getNextEntry(*n, next, hasNext); + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::getIndexProperties(Tools::PropertySet& out) const +{ + Tools::Variant var; + + // dimension + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_dimension; + out.setProperty("Dimension", var); + + // index capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexCapacity; + out.setProperty("IndexCapacity", var); + + // leaf capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafCapacity; + out.setProperty("LeafCapacity", var); + + // Tree variant + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = m_treeVariant; + out.setProperty("TreeVariant", var); + + // fill factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_fillFactor; + out.setProperty("FillFactor", var); + + // horizon + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_horizon; + out.setProperty("Horizon", var); + + // near minimum overlap factor + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_nearMinimumOverlapFactor; + out.setProperty("NearMinimumOverlapFactor", var); + + // split distribution factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_splitDistributionFactor; + out.setProperty("SplitDistributionFactor", var); + + // reinsert factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_reinsertFactor; + out.setProperty("ReinsertFactor", var); + + // tight MBRs + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = m_bTightMBRs; + out.setProperty("EnsureTightMBRs", var); + + // index pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexPool.getCapacity(); + out.setProperty("IndexPoolCapacity", var); + + // leaf pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafPool.getCapacity(); + out.setProperty("LeafPoolCapacity", var); + + // region pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_regionPool.getCapacity(); + out.setProperty("RegionPoolCapacity", var); + + // point pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_pointPool.getCapacity(); + out.setProperty("PointPoolCapacity", var); +} + +void SpatialIndex::TPRTree::TPRTree::addCommand(ICommand* pCommand, CommandType ct) +{ + switch (ct) + { + case CT_NODEREAD: + m_readNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEWRITE: + m_writeNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEDELETE: + m_deleteNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + } +} + +bool SpatialIndex::TPRTree::TPRTree::isIndexValid() +{ + bool ret = true; + + std::stack<ValidateEntry> st; + NodePtr root = readNode(m_rootID); + + if (root->m_level != m_stats.m_treeHeight - 1) + { + std::cerr << "Invalid tree height." << std::endl; + return false; + } + + std::map<uint32_t, uint32_t> nodesInLevel; + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(root->m_level, 1)); + + ValidateEntry e(root->m_nodeMBR, root); + st.push(e); + + while (! st.empty()) + { + e = st.top(); st.pop(); + + MovingRegion tmpRegion; + tmpRegion = m_infiniteRegion; + + // I have to rely on the parent information here, since none of the node's + // children might have a reference time equal to their parents (e.g., after + // a split). + tmpRegion.m_startTime = e.m_parentMBR.m_startTime; + + for (uint32_t cDim = 0; cDim < tmpRegion.m_dimension; ++cDim) + { + tmpRegion.m_pLow[cDim] = std::numeric_limits<double>::max(); + tmpRegion.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + tmpRegion.m_pVLow[cDim] = std::numeric_limits<double>::max(); + tmpRegion.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + tmpRegion.m_pLow[cDim] = std::min(tmpRegion.m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->getExtrapolatedLow(cDim, tmpRegion.m_startTime)); + tmpRegion.m_pHigh[cDim] = std::max(tmpRegion.m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, tmpRegion.m_startTime)); + tmpRegion.m_pVLow[cDim] = std::min(tmpRegion.m_pVLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pVLow[cDim]); + tmpRegion.m_pVHigh[cDim] = std::max(tmpRegion.m_pVHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + tmpRegion.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + tmpRegion.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + + if (! (tmpRegion == e.m_pNode->m_nodeMBR)) + { + std::cerr << "Invalid parent information." << std::endl; + ret = false; + } + if (! (tmpRegion == e.m_parentMBR)) + { + std::cerr << "Error in parent." << std::endl; + ret = false; + } + + if (e.m_pNode->m_level != 0) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]); + ValidateEntry tmpEntry(*(e.m_pNode->m_ptrMBR[cChild]), ptrN); + + std::map<uint32_t, uint32_t>::iterator itNodes = nodesInLevel.find(tmpEntry.m_pNode->m_level); + + if (itNodes == nodesInLevel.end()) + { + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(tmpEntry.m_pNode->m_level, 1l)); + } + else + { + nodesInLevel[tmpEntry.m_pNode->m_level] = nodesInLevel[tmpEntry.m_pNode->m_level] + 1; + } + + st.push(tmpEntry); + } + } + } + + uint32_t nodes = 0; + for (uint32_t cLevel = 0; cLevel < m_stats.m_treeHeight; ++cLevel) + { + if (nodesInLevel[cLevel] != m_stats.m_nodesInLevel[cLevel]) + { + std::cerr << "Invalid nodesInLevel information." << std::endl; + ret = false; + } + + nodes += m_stats.m_nodesInLevel[cLevel]; + } + + if (nodes != m_stats.m_nodes) + { + std::cerr << "Invalid number of nodes information." << std::endl; + ret = false; + } + + return ret; +} + +void SpatialIndex::TPRTree::TPRTree::getStatistics(IStatistics** out) const +{ + *out = new Statistics(m_stats); +} + +void SpatialIndex::TPRTree::TPRTree::initNew(Tools::PropertySet& ps) +{ + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != TPRV_RSTAR)) + throw Tools::IllegalArgumentException("initNew: Property TreeVariant must be Tools::VT_LONG and of TPRTreeVariant type"); + + m_treeVariant = static_cast<TPRTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property FillFactor must be Tools::VT_DOUBLE and in (0.0, 1.0) for RSTAR"); + + m_fillFactor = var.m_val.dblVal; + } + + // horizon + var = ps.getProperty("Horizon"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal == std::numeric_limits<double>::max()) + throw Tools::IllegalArgumentException("initNew: Property Horizon must be Tools::VT_DOUBLE and a positive constant"); + + m_horizon = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property IndexCapacity must be Tools::VT_ULONG and >= 4"); + + m_indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property LeafCapacity must be Tools::VT_ULONG and >= 4"); + + m_leafCapacity = var.m_val.ulVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be greater than 1"); + + m_dimension = var.m_val.ulVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) + throw Tools::IllegalArgumentException("initNew: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); + + m_stats.m_treeHeight = 1; + m_stats.m_nodesInLevel.push_back(0); + + Leaf root(this, -1); + m_rootID = writeNode(&root); + + storeHeader(); +} + +void SpatialIndex::TPRTree::TPRTree::initOld(Tools::PropertySet& ps) +{ + loadHeader(); + + // only some of the properties may be changed. + // the rest are just ignored. + + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != TPRV_RSTAR)) + throw Tools::IllegalArgumentException("initOld: Property TreeVariant must be Tools::VT_LONG and of TPRTreeVariant type"); + + m_treeVariant = static_cast<TPRTreeVariant>(var.m_val.lVal); + } + + // horizon + var = ps.getProperty("Horizon"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal == std::numeric_limits<double>::max()) + throw Tools::IllegalArgumentException("initOld: Property Horizon must be Tools::VT_DOUBLE and a positive constant"); + + m_horizon = var.m_val.dblVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initOld: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); +} + +void SpatialIndex::TPRTree::TPRTree::storeHeader() +{ + const uint32_t headerSize = + sizeof(id_type) + // m_rootID + sizeof(TPRTreeVariant) + // m_treeVariant + sizeof(double) + // m_fillFactor + sizeof(uint32_t) + // m_indexCapacity + sizeof(uint32_t) + // m_leafCapacity + sizeof(uint32_t) + // m_nearMinimumOverlapFactor + sizeof(double) + // m_splitDistributionFactor + sizeof(double) + // m_reinsertFactor + sizeof(uint32_t) + // m_dimension + sizeof(char) + // m_bTightMBRs + sizeof(uint32_t) + // m_stats.m_nodes + sizeof(uint64_t) + // m_stats.m_data + sizeof(double) + // m_currentTime + sizeof(double) + // m_horizon + sizeof(uint32_t) + // m_stats.m_treeHeight + m_stats.m_treeHeight * sizeof(uint32_t);// m_stats.m_nodesInLevel + + byte* header = new byte[headerSize]; + byte* ptr = header; + + memcpy(ptr, &m_rootID, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_treeVariant, sizeof(TPRTreeVariant)); + ptr += sizeof(TPRTreeVariant); + memcpy(ptr, &m_fillFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_indexCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_leafCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_nearMinimumOverlapFactor, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_splitDistributionFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_reinsertFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c = (char) m_bTightMBRs; + memcpy(ptr, &c, sizeof(char)); + ptr += sizeof(char); + memcpy(ptr, &(m_stats.m_nodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_data), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(ptr, &m_currentTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_horizon, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(m_stats.m_treeHeight), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_treeHeight; ++cLevel) + { + memcpy(ptr, &(m_stats.m_nodesInLevel[cLevel]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + m_pStorageManager->storeByteArray(m_headerID, headerSize, header); + + delete[] header; +} + +void SpatialIndex::TPRTree::TPRTree::loadHeader() +{ + uint32_t headerSize; + byte* header = 0; + m_pStorageManager->loadByteArray(m_headerID, headerSize, &header); + + byte* ptr = header; + + memcpy(&m_rootID, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&m_treeVariant, ptr, sizeof(TPRTreeVariant)); + ptr += sizeof(TPRTreeVariant); + memcpy(&m_fillFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_indexCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_leafCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_nearMinimumOverlapFactor, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_splitDistributionFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_reinsertFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c; + memcpy(&c, ptr, sizeof(char)); + m_bTightMBRs = (c != 0); + ptr += sizeof(char); + memcpy(&(m_stats.m_nodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_data), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(&m_currentTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_horizon, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(m_stats.m_treeHeight), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_treeHeight; ++cLevel) + { + uint32_t cNodes; + memcpy(&cNodes, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + m_stats.m_nodesInLevel.push_back(cNodes); + } + + delete[] header; +} + +void SpatialIndex::TPRTree::TPRTree::insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mr, id_type id) +{ + assert(mr.getDimension() == m_dimension); + assert(m_currentTime <= mr.m_startTime); + + std::stack<id_type> pathBuffer; + byte* overflowTable = 0; + + try + { + NodePtr root = readNode(m_rootID); + + overflowTable = new byte[root->m_level]; + bzero(overflowTable, root->m_level); + + NodePtr l = root->chooseSubtree(mr, 0, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mr, id, pathBuffer, overflowTable); + + delete[] overflowTable; + ++(m_stats.m_data); + } + catch (...) + { + delete[] overflowTable; + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mr, id_type id, uint32_t level, byte* overflowTable) +{ + assert(mr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_rootID); + NodePtr n = root->chooseSubtree(mr, level, pathBuffer); + + assert(n->m_level == level); + + if (n.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + n->insertData(dataLength, pData, mr, id, pathBuffer, overflowTable); +} + +bool SpatialIndex::TPRTree::TPRTree::deleteData_impl(const MovingRegion& mr, id_type id) +{ + assert(mr.m_dimension == m_dimension); + + std::stack<id_type> pathBuffer; + + NodePtr root = readNode(m_rootID); + NodePtr l = root->findLeaf(mr, id, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + + if (l.get() != 0) + { + Leaf* pL = static_cast<Leaf*>(l.get()); + pL->deleteData(id, pathBuffer); + --(m_stats.m_data); + return true; + } + + return false; +} + +id_type SpatialIndex::TPRTree::TPRTree::writeNode(Node* n) +{ + byte* buffer; + uint32_t dataLength; + n->storeToByteArray(&buffer, dataLength); + + id_type page; + if (n->m_identifier < 0) page = StorageManager::NewPage; + else page = n->m_identifier; + + try + { + m_pStorageManager->storeByteArray(page, dataLength, buffer); + delete[] buffer; + } + catch (InvalidPageException& e) + { + delete[] buffer; + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("writeNode: failed with Tools::InvalidPageException"); + } + + if (n->m_identifier < 0) + { + n->m_identifier = page; + ++(m_stats.m_nodes); + +#ifndef NDEBUG + try + { + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel.at(n->m_level) + 1; + } + catch(...) + { + throw Tools::IllegalStateException("writeNode: writing past the end of m_nodesInLevel."); + } +#else + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] + 1; +#endif + } + + ++(m_stats.m_writes); + + for (size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex) + { + m_writeNodeCommands[cIndex]->execute(*n); + } + + return page; +} + +SpatialIndex::TPRTree::NodePtr SpatialIndex::TPRTree::TPRTree::readNode(id_type id) +{ + uint32_t dataLength; + byte* buffer; + + try + { + m_pStorageManager->loadByteArray(id, dataLength, &buffer); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("readNode: failed with Tools::InvalidPageException"); + } + + try + { + uint32_t nodeType; + memcpy(&nodeType, buffer, sizeof(uint32_t)); + + NodePtr n; + + if (nodeType == PersistentIndex) n = m_indexPool.acquire(); + else if (nodeType == PersistentLeaf) n = m_leafPool.acquire(); + else throw Tools::IllegalStateException("readNode: failed reading the correct node type information"); + + if (n.get() == 0) + { + if (nodeType == PersistentIndex) n = NodePtr(new Index(this, -1, 0), &m_indexPool); + else if (nodeType == PersistentLeaf) n = NodePtr(new Leaf(this, -1), &m_leafPool); + } + + //n->m_pTree = this; + n->m_identifier = id; + n->loadFromByteArray(buffer); + + ++(m_stats.m_reads); + + for (size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex) + { + m_readNodeCommands[cIndex]->execute(*n); + } + + delete[] buffer; + return n; + } + catch (...) + { + delete[] buffer; + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::deleteNode(Node* n) +{ + try + { + m_pStorageManager->deleteByteArray(n->m_identifier); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("deleteNode: failed with Tools::InvalidPageException"); + } + + --(m_stats.m_nodes); + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] - 1; + + for (size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex) + { + m_deleteNodeCommands[cIndex]->execute(*n); + } +} + +void SpatialIndex::TPRTree::TPRTree::rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v) +{ + const MovingRegion* mr = dynamic_cast<const MovingRegion*>(&query); + if (mr == 0) throw Tools::IllegalArgumentException("rangeQuery: Shape has to be a moving region."); + if (mr->m_startTime < m_currentTime || mr->m_endTime >= m_currentTime + m_horizon) + throw Tools::IllegalArgumentException("rangeQuery: Query time interval does not intersect current horizon."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("rangeQuery: cannot acquire a shared lock"); +#endif + + try + { + std::stack<NodePtr> st; + NodePtr root = readNode(m_rootID); + + if (root->m_children > 0 && mr->intersectsRegionInTime(root->m_nodeMBR)) st.push(root); + + while (! st.empty()) + { + NodePtr n = st.top(); st.pop(); + + if (n->m_level == 0) + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + bool b; + if (type == ContainmentQuery) b = mr->containsRegionInTime(*(n->m_ptrMBR[cChild])); + else b = mr->intersectsRegionInTime(*(n->m_ptrMBR[cChild])); + + if (b) + { + Data data = Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + v.visitData(data); + ++(m_stats.m_queryResults); + } + } + } + else + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (mr->intersectsRegionInTime(*(n->m_ptrMBR[cChild]))) st.push(readNode(n->m_pIdentifier[cChild])); + } + } + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +std::ostream& SpatialIndex::TPRTree::operator<<(std::ostream& os, const TPRTree& t) +{ + os << "Dimension: " << t.m_dimension << std::endl + << "Fill factor: " << t.m_fillFactor << std::endl + << "Horizon: " << t.m_horizon << std::endl + << "Index capacity: " << t.m_indexCapacity << std::endl + << "Leaf capacity: " << t.m_leafCapacity << std::endl + << "Tight MBRs: " << ((t.m_bTightMBRs) ? "enabled" : "disabled") << std::endl; + + if (t.m_treeVariant == TPRV_RSTAR) + { + os << "Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl + << "Reinsert factor: " << t.m_reinsertFactor << std::endl + << "Split distribution factor: " << t.m_splitDistributionFactor << std::endl; + } + + if (t.m_stats.getNumberOfNodesInLevel(0) > 0) + os << "Utilization: " << 100 * t.m_stats.getNumberOfData() / (t.m_stats.getNumberOfNodesInLevel(0) * t.m_leafCapacity) << "%" << std::endl + << t.m_stats; + + #ifndef NDEBUG + os << "Leaf pool hits: " << t.m_leafPool.m_hits << std::endl + << "Leaf pool misses: " << t.m_leafPool.m_misses << std::endl + << "Index pool hits: " << t.m_indexPool.m_hits << std::endl + << "Index pool misses: " << t.m_indexPool.m_misses << std::endl + << "Region pool hits: " << t.m_regionPool.m_hits << std::endl + << "Region pool misses: " << t.m_regionPool.m_misses << std::endl + << "Point pool hits: " << t.m_pointPool.m_hits << std::endl + << "Point pool misses: " << t.m_pointPool.m_misses << std::endl; + #endif + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/TPRTree.h.svn-base b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/TPRTree.h.svn-base new file mode 100644 index 000000000..2c28727cd --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/.svn/text-base/TPRTree.h.svn-base @@ -0,0 +1,199 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Statistics.h" +#include "Node.h" +#include "PointerPoolNode.h" + +namespace SpatialIndex +{ + namespace TPRTree + { + class TPRTree : public ISpatialIndex + { + class NNEntry; + + public: + TPRTree(IStorageManager&, Tools::PropertySet&); + // String Value Description + // ---------------------------------------------- + // IndexIndentifier VT_LONG If specified an existing index will be openened from the supplied + // storage manager with the given index id. Behaviour is unspecified + // if the index id or the storage manager are incorrect. + // Dimension VT_ULONG Dimensionality of the data that will be inserted. + // IndexCapacity VT_ULONG The index node capacity. Default is 100. + // LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. + // FillFactor VT_DOUBLE The fill factor. Default is 70% + // Horizon VT_DOUBLE Horizon. Default is 20.0. + // TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar + // NearMinimumOverlapFactor VT_ULONG Default is 32. + // SplitDistributionFactor VT_DOUBLE Default is 0.4 + // ReinsertFactor VT_DOUBLE Default is 0.3 + // EnsureTightMBRs VT_BOOL Default is true + // IndexPoolCapacity VT_LONG Default is 100 + // LeafPoolCapacity VT_LONG Default is 100 + // RegionPoolCapacity VT_LONG Default is 1000 + // PointPoolCapacity VT_LONG Default is 500 + + virtual ~TPRTree(); + + // + // ISpatialIndex interface + // + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type shapeIdentifier); + virtual bool deleteData(const IShape& shape, id_type id); + virtual void containsWhatQuery(const IShape& query, IVisitor& v); + virtual void intersectsWithQuery(const IShape& query, IVisitor& v); + virtual void pointLocationQuery(const Point& query, IVisitor& v); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator&); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v); + virtual void selfJoinQuery(const IShape& s, IVisitor& v); + virtual void queryStrategy(IQueryStrategy& qs); + virtual void getIndexProperties(Tools::PropertySet& out) const; + virtual void addCommand(ICommand* pCommand, CommandType ct); + virtual bool isIndexValid(); + virtual void getStatistics(IStatistics** out) const; + + private: + void initNew(Tools::PropertySet&); + void initOld(Tools::PropertySet& ps); + void storeHeader(); + void loadHeader(); + + void insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id); + void insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, uint32_t level, byte* overflowTable); + bool deleteData_impl(const MovingRegion& mbr, id_type id); + + id_type writeNode(Node*); + NodePtr readNode(id_type id); + void deleteNode(Node*); + + void rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v); + + IStorageManager* m_pStorageManager; + + id_type m_rootID, m_headerID; + + TPRTreeVariant m_treeVariant; + + double m_fillFactor; + + uint32_t m_indexCapacity; + + uint32_t m_leafCapacity; + + uint32_t m_nearMinimumOverlapFactor; + // The R*-Tree 'p' constant, for calculating nearly minimum overlap cost. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.1] + + double m_splitDistributionFactor; + // The R*-Tree 'm' constant, for calculating spliting distributions. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.2] + + double m_reinsertFactor; + // The R*-Tree 'p' constant, for removing entries at reinserts. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.3] + + uint32_t m_dimension; + + MovingRegion m_infiniteRegion; + + Statistics m_stats; + + bool m_bTightMBRs; + + double m_currentTime; + + double m_horizon; + + Tools::PointerPool<Point> m_pointPool; + Tools::PointerPool<MovingRegion> m_regionPool; + Tools::PointerPool<Node> m_indexPool; + Tools::PointerPool<Node> m_leafPool; + + std::vector<Tools::SmartPointer<ICommand> > m_writeNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_readNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_deleteNodeCommands; + +#ifdef HAVE_PTHREAD_H + pthread_rwlock_t m_rwLock; +#else + bool m_rwLock; +#endif + + class NNEntry + { + public: + id_type m_id; + IEntry* m_pEntry; + double m_minDist; + + NNEntry(id_type id, IEntry* e, double f) : m_id(id), m_pEntry(e), m_minDist(f) {} + ~NNEntry() {} + + struct ascending : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_minDist > __y->m_minDist; } + }; + }; // NNEntry + + class NNComparator : public INearestNeighborComparator + { + public: + double getMinimumDistance(const IShape& query, const IShape& entry) + { + return query.getMinimumDistance(entry); + } + + double getMinimumDistance(const IShape& query, const IData& data) + { + IShape* pS; + data.getShape(&pS); + double ret = query.getMinimumDistance(*pS); + delete pS; + return ret; + } + }; // NNComparator + + class ValidateEntry + { + public: + ValidateEntry(MovingRegion& r, NodePtr& pNode) : m_parentMBR(r), m_pNode(pNode) {} + + MovingRegion m_parentMBR; + NodePtr m_pNode; + }; // ValidateEntry + + friend class Node; + friend class Leaf; + friend class Index; + + friend std::ostream& operator<<(std::ostream& os, const TPRTree& t); + }; // TPRTree + + std::ostream& operator<<(std::ostream& os, const TPRTree& t); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Index.cc b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Index.cc new file mode 100644 index 000000000..574414812 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Index.cc @@ -0,0 +1,400 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "TPRTree.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" + +using namespace SpatialIndex::TPRTree; + +Index::~Index() +{ +} + +Index::Index(SpatialIndex::TPRTree::TPRTree* pTree, id_type id, uint32_t level) : Node(pTree, id, level, pTree->m_indexCapacity) +{ +} + +NodePtr Index::chooseSubtree(const MovingRegion& mbr, uint32_t insertionLevel, std::stack<id_type>& pathBuffer) +{ + if (m_level == insertionLevel) return NodePtr(this, &(m_pTree->m_indexPool)); + + pathBuffer.push(m_identifier); + + uint32_t child = 0; + + switch (m_pTree->m_treeVariant) + { + case TPRV_RSTAR: + if (m_level == 1) + { + // if this node points to leaves... + child = findLeastOverlap(mbr); + } + else + { + child = findLeastEnlargement(mbr); + } + break; + default: + throw Tools::NotSupportedException("Index::chooseSubtree: Tree variant not supported."); + } + assert(child != std::numeric_limits<uint32_t>::max()); + + NodePtr n = m_pTree->readNode(m_pIdentifier[child]); + NodePtr ret = n->chooseSubtree(mbr, insertionLevel, pathBuffer); + assert(n.unique()); + if (ret.get() == n.get()) n.relinquish(); + + return ret; +} + +NodePtr Index::findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + pathBuffer.push(m_identifier); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_ptrMBR[cChild]->containsRegionAfterTime(m_pTree->m_currentTime, mbr)) + { + NodePtr n = m_pTree->readNode(m_pIdentifier[cChild]); + NodePtr l = n->findLeaf(mbr, id, pathBuffer); + if (n.get() == l.get()) n.relinquish(); + if (l.get() != 0) return l; + } + } + + pathBuffer.pop(); + + return NodePtr(); +} + +void Index::split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight) +{ + ++(m_pTree->m_stats.m_splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case TPRV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Index::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_indexPool.acquire(); + pRight = m_pTree->m_indexPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Index(m_pTree, m_identifier, m_level), &(m_pTree->m_indexPool)); + if (pRight.get() == 0) pRight = NodePtr(new Index(m_pTree, -1, m_level), &(m_pTree->m_indexPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(0, 0, *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(0, 0, *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + } +} + +uint32_t Index::findLeastEnlargement(const MovingRegion& r) const +{ + double area = std::numeric_limits<double>::max(); + uint32_t best = std::numeric_limits<uint32_t>::max(); + + MovingRegionPtr t = m_pTree->m_regionPool.acquire(); + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // I need the combined region from current time up to infinity here. + m_ptrMBR[cChild]->getCombinedRegionAfterTime(ivT.getLowerBound(), *t, r); + + double a = m_ptrMBR[cChild]->getAreaInTime(ivT); + double b = t->getAreaInTime(ivT); + double enl = b - a; + + if (enl < area) + { + area = enl; + best = cChild; + } + else if (enl == area) + { + // this will rarely happen, so compute best area on the fly only + // when necessary. + if (a < m_ptrMBR[best]->getAreaInTime(ivT)) best = cChild; + } + } + + return best; +} + +uint32_t Index::findLeastOverlap(const MovingRegion& r) const +{ + OverlapEntry** entries = new OverlapEntry*[m_children]; + + double leastOverlap = std::numeric_limits<double>::max(); + double me = std::numeric_limits<double>::max(); + OverlapEntry* best = 0; + + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + // find combined region and enlargement of every entry and store it. + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + try + { + entries[cChild] = new OverlapEntry(); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete entries[i]; + delete[] entries; + throw; + } + + entries[cChild]->m_index = cChild; + entries[cChild]->m_original = m_ptrMBR[cChild]; + entries[cChild]->m_combined = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->getCombinedRegionAfterTime(m_pTree->m_currentTime, *(entries[cChild]->m_combined), r); + entries[cChild]->m_oa = entries[cChild]->m_original->getAreaInTime(ivT); + entries[cChild]->m_ca = entries[cChild]->m_combined->getAreaInTime(ivT); + entries[cChild]->m_enlargement = entries[cChild]->m_ca - entries[cChild]->m_oa; + + if (entries[cChild]->m_enlargement < me) + { + me = entries[cChild]->m_enlargement; + best = entries[cChild]; + } + else if (entries[cChild]->m_enlargement == me && entries[cChild]->m_oa < best->m_oa) + { + best = entries[cChild]; + } + } + + if (me < -std::numeric_limits<double>::epsilon() || me > std::numeric_limits<double>::epsilon()) + { + uint32_t cIterations; + + if (m_children > m_pTree->m_nearMinimumOverlapFactor) + { + // sort entries in increasing order of enlargement. + ::qsort(entries, m_children, + sizeof(OverlapEntry*), + OverlapEntry::compareEntries); + assert(entries[0]->m_enlargement <= entries[m_children - 1]->m_enlargement); + + cIterations = m_pTree->m_nearMinimumOverlapFactor; + } + else + { + cIterations = m_children; + } + + // calculate overlap of most important original entries (near minimum overlap cost). + for (uint32_t cIndex = 0; cIndex < cIterations; ++cIndex) + { + double dif = 0.0; + OverlapEntry* e = entries[cIndex]; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (e->m_index != cChild) + { + double f = e->m_combined->getIntersectingAreaInTime(ivT, *(m_ptrMBR[cChild])); + if (f != 0.0) dif += f - e->m_original->getIntersectingAreaInTime(ivT, *(m_ptrMBR[cChild])); + } + } // for (cChild) + + if (dif < leastOverlap) + { + leastOverlap = dif; + best = entries[cIndex]; + } + else if (dif == leastOverlap) + { + if (e->m_enlargement == best->m_enlargement) + { + // keep the one with least area. + if (e->m_original->getAreaInTime(ivT) < best->m_original->getAreaInTime(ivT)) best = entries[cIndex]; + } + else + { + // keep the one with least enlargement. + if (e->m_enlargement < best->m_enlargement) best = entries[cIndex]; + } + } + } // for (cIndex) + } + + uint32_t ret = best->m_index; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + delete entries[cChild]; + } + delete[] entries; + + return ret; +} + +void Index::adjustTree(Node* n, std::stack<id_type>& pathBuffer) +{ + ++(m_pTree->m_stats.m_adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n->m_identifier) break; + } + assert(child < m_children); + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + //Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + //bool bContained = m_nodeMBR.containsRegionInTime(ivT, n->m_nodeMBR); + + *(m_ptrMBR[child]) = n->m_nodeMBR; + + //if (! bContained) + //{ + // update the MBR at the current time anyway, to make tighter. + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + //} + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, *(m_ptrMBR[cChild])) == true); + } +#endif + + m_pTree->writeNode(this); + + if (/*! bContained && */ ! pathBuffer.empty()) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} + +void Index::adjustTree(Node* n1, Node* n2, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + ++(m_pTree->m_stats.m_adjustments); + + // find entry pointing to old node; + uint32_t child; + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == n1->m_identifier) break; + } + assert(child < m_children); + + // MBR needs recalculation if either: + // 1. the NEW child MBR is not contained. + // 2. the OLD child MBR is touching. + //Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + //bool bContained = m_nodeMBR.containsRegionInTime(ivT, n1->m_nodeMBR); + + *(m_ptrMBR[child]) = n1->m_nodeMBR; + + //if (! bContaied) + //{ + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + //} + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, *(m_ptrMBR[cChild])) == true); + } +#endif + + // No write necessary here. insertData will write the node if needed. + //m_pTree->writeNode(this); + + bool bAdjusted = insertData(0, 0, n2->m_nodeMBR, n2->m_identifier, pathBuffer, overflowTable); + + // if n2 is contained in the node and there was no split or reinsert, + // we need to adjust only if recalculation took place. + // In all other cases insertData above took care of adjustment. + if (! bAdjusted && ! pathBuffer.empty()) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Index.h b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Index.h new file mode 100644 index 000000000..68ca1f51f --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Index.h @@ -0,0 +1,73 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class Index : public Node + { + public: + virtual ~Index(); + + private: + Index(TPRTree* pTree, id_type id, uint32_t level); + + virtual NodePtr chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& left, NodePtr& right); + + uint32_t findLeastEnlargement(const MovingRegion&) const; + uint32_t findLeastOverlap(const MovingRegion&) const; + + void adjustTree(Node*, std::stack<id_type>&); + void adjustTree(Node*, Node*, std::stack<id_type>&, byte* overflowTable); + + class OverlapEntry + { + public: + uint32_t m_index; + double m_enlargement; + MovingRegionPtr m_original; + MovingRegionPtr m_combined; + double m_oa; + double m_ca; + + static int compareEntries(const void* pv1, const void* pv2) + { + OverlapEntry* pe1 = * (OverlapEntry**) pv1; + OverlapEntry* pe2 = * (OverlapEntry**) pv2; + + if (pe1->m_enlargement < pe2->m_enlargement) return -1; + if (pe1->m_enlargement > pe2->m_enlargement) return 1; + return 0; + } + }; // OverlapEntry + + friend class TPRTree; + friend class Node; + friend class BulkLoader; + }; // Index + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Leaf.cc b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Leaf.cc new file mode 100644 index 000000000..a9db9df2c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Leaf.cc @@ -0,0 +1,135 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "TPRTree.h" +#include "Node.h" +#include "Index.h" +#include "Leaf.h" + +using namespace SpatialIndex::TPRTree; + +Leaf::~Leaf() +{ +} + +Leaf::Leaf(SpatialIndex::TPRTree::TPRTree* pTree, id_type id) + : Node(pTree, id, 0, pTree->m_leafCapacity) +{ +} + +NodePtr Leaf::chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) +{ + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + return NodePtr(this, &(m_pTree->m_leafPool)); +} + +NodePtr Leaf::findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) +{ + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + // should make sure to relinquish other PoolPointer lists that might be pointing to the + // same leaf. + if (m_pIdentifier[cChild] == id /*&& mbr == *(m_ptrMBR[cChild])*/) return NodePtr(this, &(m_pTree->m_leafPool)); + } + + return NodePtr(); +} + +void Leaf::split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& pLeft, NodePtr& pRight) +{ + ++(m_pTree->m_stats.m_splits); + + std::vector<uint32_t> g1, g2; + + switch (m_pTree->m_treeVariant) + { + case TPRV_RSTAR: + rstarSplit(dataLength, pData, mbr, id, g1, g2); + break; + default: + throw Tools::NotSupportedException("Leaf::split: Tree variant not supported."); + } + + pLeft = m_pTree->m_leafPool.acquire(); + pRight = m_pTree->m_leafPool.acquire(); + + if (pLeft.get() == 0) pLeft = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + if (pRight.get() == 0) pRight = NodePtr(new Leaf(m_pTree, -1), &(m_pTree->m_leafPool)); + + pLeft->m_nodeMBR = m_pTree->m_infiniteRegion; + pRight->m_nodeMBR = m_pTree->m_infiniteRegion; + + uint32_t cIndex; + + for (cIndex = 0; cIndex < g1.size(); ++cIndex) + { + pLeft->insertEntry(m_pDataLength[g1[cIndex]], m_pData[g1[cIndex]], *(m_ptrMBR[g1[cIndex]]), m_pIdentifier[g1[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g1[cIndex]] = 0; + } + + for (cIndex = 0; cIndex < g2.size(); ++cIndex) + { + pRight->insertEntry(m_pDataLength[g2[cIndex]], m_pData[g2[cIndex]], *(m_ptrMBR[g2[cIndex]]), m_pIdentifier[g2[cIndex]]); + // we don't want to delete the data array from this node's destructor! + m_pData[g2[cIndex]] = 0; + } +} + +void Leaf::deleteData(id_type id, std::stack<id_type>& pathBuffer) +{ + uint32_t child; + + for (child = 0; child < m_children; ++child) + { + if (m_pIdentifier[child] == id) break; + } + + deleteEntry(child); + m_pTree->writeNode(this); + + std::stack<NodePtr> toReinsert; + NodePtr ptrThis(this, &(m_pTree->m_leafPool)); + condenseTree(toReinsert, pathBuffer, ptrThis); + ptrThis.relinquish(); + + // re-insert eliminated nodes. + while (! toReinsert.empty()) + { + NodePtr n = toReinsert.top(); toReinsert.pop(); + m_pTree->deleteNode(n.get()); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + // keep this in the for loop. The tree height might change after insertions. + byte* overflowTable = new byte[m_pTree->m_stats.m_treeHeight]; + bzero(overflowTable, m_pTree->m_stats.m_treeHeight); + m_pTree->insertData_impl(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild], n->m_level, overflowTable); + n->m_pData[cChild] = 0; + delete[] overflowTable; + } + if (n.get() == this) n.relinquish(); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Leaf.h b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Leaf.h new file mode 100644 index 000000000..01a0bd53c --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Leaf.h @@ -0,0 +1,47 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class Leaf : public Node + { + public: + virtual ~Leaf(); + + private: + Leaf(TPRTree* pTree, id_type id); + + virtual NodePtr chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer); + virtual NodePtr findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer); + + virtual void split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& left, NodePtr& right); + + virtual void deleteData(id_type id, std::stack<id_type>& pathBuffer); + + friend class TPRTree; + friend class BulkLoader; + }; // Leaf + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Makefile.am b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Makefile.am new file mode 100644 index 000000000..6f6a87aa2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Makefile.am @@ -0,0 +1,4 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +noinst_LTLIBRARIES = libtprtree.la +INCLUDES = -I../../include +libtprtree_la_SOURCES = Index.cc Leaf.cc Node.cc TPRTree.cc Statistics.cc Leaf.h Index.h Node.h PointerPoolNode.h Statistics.h TPRTree.h diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Node.cc b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Node.cc new file mode 100644 index 000000000..1c14b99c2 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Node.cc @@ -0,0 +1,1253 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <cstring> +#include <cmath> +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "TPRTree.h" +#include "Node.h" +#include "Index.h" + +using namespace SpatialIndex::TPRTree; + +// +// Tools::IObject interface +// +Tools::IObject* Node::clone() +{ + throw Tools::NotSupportedException("IObject::clone should never be called."); +} + +// +// Tools::ISerializable interface +// +uint32_t Node::getByteArraySize() +{ + return + (sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(uint32_t) + + sizeof(double) + + (m_children * (4 * m_pTree->m_dimension * sizeof(double) + sizeof(double) + sizeof(id_type) + sizeof(uint32_t))) + + m_totalDataLength + + (4 * m_pTree->m_dimension * sizeof(double))); +} + +void Node::loadFromByteArray(const byte* ptr) +{ + m_nodeMBR = m_pTree->m_infiniteRegion; + + // skip the node type information, it is not needed. + ptr += sizeof(uint32_t); + + memcpy(&m_level, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&m_children, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(&(m_nodeMBR.m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + m_nodeMBR.m_endTime = std::numeric_limits<double>::max(); + //memcpy(&(m_nodeMBR.m_endTime), ptr, sizeof(double)); + //ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_ptrMBR[cChild] = m_pTree->m_regionPool.acquire(); + m_ptrMBR[cChild]->makeDimension(m_pTree->m_dimension); + + memcpy(m_ptrMBR[cChild]->m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pVLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_ptrMBR[cChild]->m_pVHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(&(m_ptrMBR[cChild]->m_startTime), ptr, sizeof(double)); + ptr += sizeof(double); + m_ptrMBR[cChild]->m_endTime = std::numeric_limits<double>::max(); + + memcpy(&(m_pIdentifier[cChild]), ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(&(m_pDataLength[cChild]), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + m_totalDataLength += m_pDataLength[cChild]; + m_pData[cChild] = new byte[m_pDataLength[cChild]]; + memcpy(m_pData[cChild], ptr, m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + else + { + m_pData[cChild] = 0; + } + + //m_nodeMBR.combineRegion(*(m_ptrMBR[cChild])); + } + + memcpy(m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pVLow, ptr, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(m_nodeMBR.m_pVHigh, ptr, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); +} + +void Node::storeToByteArray(byte** data, uint32_t& len) +{ + len = getByteArraySize(); + + *data = new byte[len]; + byte* ptr = *data; + + uint32_t nodeType; + + if (m_level == 0) nodeType = PersistentLeaf; + else nodeType = PersistentIndex; + + memcpy(ptr, &nodeType, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_level, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &m_children, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + memcpy(ptr, &(m_nodeMBR.m_startTime), sizeof(double)); + ptr += sizeof(double); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + memcpy(ptr, m_ptrMBR[cChild]->m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pVLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_ptrMBR[cChild]->m_pVHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, &(m_ptrMBR[cChild]->m_startTime), sizeof(double)); + ptr += sizeof(double); + + memcpy(ptr, &(m_pIdentifier[cChild]), sizeof(id_type)); + ptr += sizeof(id_type); + + memcpy(ptr, &(m_pDataLength[cChild]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_pDataLength[cChild] > 0) + { + memcpy(ptr, m_pData[cChild], m_pDataLength[cChild]); + ptr += m_pDataLength[cChild]; + } + } + + // store the node MBR for efficiency. This increases the node size a little bit. + memcpy(ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pVLow, m_pTree->m_dimension * sizeof(double)); + ptr += m_pTree->m_dimension * sizeof(double); + memcpy(ptr, m_nodeMBR.m_pVHigh, m_pTree->m_dimension * sizeof(double)); + //ptr += m_pTree->m_dimension * sizeof(double); + + assert(len == (ptr - *data) + m_pTree->m_dimension * sizeof(double)); +} + +// +// SpatialIndex::IEntry interface +// +id_type Node::getIdentifier() const +{ + return m_identifier; +} + +void Node::getShape(IShape** out) const +{ + *out = new MovingRegion(m_nodeMBR); +} + +// +// SpatialIndex::INode interface +// +uint32_t Node::getChildrenCount() const +{ + return m_children; +} + +id_type Node::getChildIdentifier(uint32_t index) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + return m_pIdentifier[index]; +} + +void Node::getChildShape(uint32_t index, IShape** out) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + + *out = new MovingRegion(*(m_ptrMBR[index])); +} + +void Node::getChildData(uint32_t index, uint32_t& length, byte** data) const +{ + if (index < 0 || index >= m_children) throw Tools::IndexOutOfBoundsException(index); + if (m_pData[index] == NULL) + { + length = 0; + data = NULL; + } + else + { + length = m_pDataLength[index]; + *data = m_pData[index]; + } +} + +uint32_t Node::getLevel() const +{ + return m_level; +} + +bool Node::isLeaf() const +{ + return (m_level == 0); +} + +bool Node::isIndex() const +{ + return (m_level != 0); +} + +// +// Internal +// + +Node::Node() : + m_pTree(0), + m_level(0), + m_identifier(-1), + m_children(0), + m_capacity(0), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ +} + +Node::Node(SpatialIndex::TPRTree::TPRTree* pTree, id_type id, uint32_t level, uint32_t capacity) : + m_pTree(pTree), + m_level(level), + m_identifier(id), + m_children(0), + m_capacity(capacity), + m_pData(0), + m_ptrMBR(0), + m_pIdentifier(0), + m_pDataLength(0), + m_totalDataLength(0) +{ + m_nodeMBR.makeInfinite(m_pTree->m_dimension); + + try + { + m_pDataLength = new uint32_t[m_capacity + 1]; + m_pData = new byte*[m_capacity + 1]; + m_ptrMBR = new MovingRegionPtr[m_capacity + 1]; + m_pIdentifier = new id_type[m_capacity + 1]; + } + catch (...) + { + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + throw; + } +} + +Node::~Node() +{ + if (m_pData != 0) + { + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + if (m_pData[cChild] != 0) delete[] m_pData[cChild]; + } + + delete[] m_pData; + } + + delete[] m_pDataLength; + delete[] m_ptrMBR; + delete[] m_pIdentifier; +} + +Node& Node::operator=(const Node& n) +{ + throw Tools::IllegalStateException("Node::operator =: This should never be called."); +} + +bool Node::insertEntry(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id) +{ + assert(m_children < m_capacity); + + bool bAdjusted = false; + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + m_totalDataLength += dataLength; + ++m_children; + + if (m_nodeMBR.m_startTime != m_pTree->m_currentTime) + { + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + + bAdjusted = true; + } + else if ( + //m_nodeMBR.m_pLow[0] != std::numeric_limits<double>::max() && + ! m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, mbr)) + { + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + double l = m_nodeMBR.getExtrapolatedLow(cDim, m_pTree->m_currentTime); + double rl = mbr.getExtrapolatedLow(cDim, m_pTree->m_currentTime); + if (rl <= l) + { + m_nodeMBR.m_pLow[cDim] = rl - 2.0 * std::numeric_limits<double>::epsilon(); + } + + double h = m_nodeMBR.getExtrapolatedHigh(cDim, m_pTree->m_currentTime); + double rh = mbr.getExtrapolatedHigh(cDim, m_pTree->m_currentTime); + if (rh >= h) + { + m_nodeMBR.m_pHigh[cDim] = rh + 2.0 * std::numeric_limits<double>::epsilon(); + } + + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], mbr.m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], mbr.m_pVHigh[cDim]); + } + + bAdjusted = true; + } + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_nodeMBR.m_startTime, *(m_ptrMBR[cChild]))); + } +#endif + + return true; +} + +void Node::deleteEntry(uint32_t index) +{ + assert(index >= 0 && index < m_children); + + // cache it, since I might need it for "touches" later. + MovingRegionPtr ptrR = m_ptrMBR[index]; + + m_totalDataLength -= m_pDataLength[index]; + if (m_pData[index] != 0) delete[] m_pData[index]; + + if (m_children > 1 && index != m_children - 1) + { + m_pDataLength[index] = m_pDataLength[m_children - 1]; + m_pData[index] = m_pData[m_children - 1]; + m_ptrMBR[index] = m_ptrMBR[m_children - 1]; + m_pIdentifier[index] = m_pIdentifier[m_children - 1]; + } + + --m_children; + + // WARNING: index has now changed. Do not use it below here. + + if (m_children == 0) + { + m_nodeMBR = m_pTree->m_infiniteRegion; + } + else //if (m_pTree->m_bTightMBRs && m_nodeMBR.touchesRegion(*ptrR)) + { + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_pTree->m_currentTime, *(m_ptrMBR[cChild])) == true); + } +#endif + } +} + +bool Node::insertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable) +{ + if (m_children < m_capacity) + { + bool bNeedToAdjust = insertEntry(dataLength, pData, mbr, id); + m_pTree->writeNode(this); + + if (bNeedToAdjust && ! pathBuffer.empty()) + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + } + + return bNeedToAdjust; + } + else if (false && m_pTree->m_treeVariant == TPRV_RSTAR && ! pathBuffer.empty() && overflowTable[m_level] == 0) + { + overflowTable[m_level] = 1; + + std::vector<uint32_t> vReinsert, vKeep; + reinsertData(dataLength, pData, mbr, id, vReinsert, vKeep); + + uint32_t lReinsert = static_cast<uint32_t>(vReinsert.size()); + uint32_t lKeep = static_cast<uint32_t>(vKeep.size()); + + byte** reinsertdata = 0; + MovingRegionPtr* reinsertmbr = 0; + id_type* reinsertid = 0; + uint32_t* reinsertlen = 0; + byte** keepdata = 0; + MovingRegionPtr* keepmbr = 0; + id_type* keepid = 0; + uint32_t* keeplen = 0; + + try + { + reinsertdata = new byte*[lReinsert]; + reinsertmbr = new MovingRegionPtr[lReinsert]; + reinsertid = new id_type[lReinsert]; + reinsertlen = new uint32_t[lReinsert]; + + keepdata = new byte*[m_capacity + 1]; + keepmbr = new MovingRegionPtr[m_capacity + 1]; + keepid = new id_type[m_capacity + 1]; + keeplen = new uint32_t[m_capacity + 1]; + } + catch (...) + { + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + delete[] keepdata; + delete[] keepmbr; + delete[] keepid; + delete[] keeplen; + throw; + } + + uint32_t cIndex; + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + reinsertlen[cIndex] = m_pDataLength[vReinsert[cIndex]]; + reinsertdata[cIndex] = m_pData[vReinsert[cIndex]]; + reinsertmbr[cIndex] = m_ptrMBR[vReinsert[cIndex]]; + reinsertid[cIndex] = m_pIdentifier[vReinsert[cIndex]]; + } + + for (cIndex = 0; cIndex < lKeep; ++cIndex) + { + keeplen[cIndex] = m_pDataLength[vKeep[cIndex]]; + keepdata[cIndex] = m_pData[vKeep[cIndex]]; + keepmbr[cIndex] = m_ptrMBR[vKeep[cIndex]]; + keepid[cIndex] = m_pIdentifier[vKeep[cIndex]]; + } + + delete[] m_pDataLength; + delete[] m_pData; + delete[] m_ptrMBR; + delete[] m_pIdentifier; + + m_pDataLength = keeplen; + m_pData = keepdata; + m_ptrMBR = keepmbr; + m_pIdentifier = keepid; + m_children = lKeep; + m_totalDataLength = 0; + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) m_totalDataLength += m_pDataLength[cChild]; + + m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < m_nodeMBR.m_dimension; ++cDim) + { + m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + m_nodeMBR.m_pLow[cDim] = std::min(m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pHigh[cDim] = std::max(m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_nodeMBR.m_startTime)); + m_nodeMBR.m_pVLow[cDim] = std::min(m_nodeMBR.m_pVLow[cDim], m_ptrMBR[cChild]->m_pVLow[cDim]); + m_nodeMBR.m_pVHigh[cDim] = std::max(m_nodeMBR.m_pVHigh[cDim], m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < m_children; ++cChild) + { + assert(m_nodeMBR.containsRegionAfterTime(m_nodeMBR.m_startTime, *(m_ptrMBR[cChild]))); + } +#endif + + m_pTree->writeNode(this); + + // Divertion from R*-Tree algorithm here. First adjust + // the path to the root, then start reinserts, to avoid complicated handling + // of changes to the same node from multiple insertions. + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(this, pathBuffer); + + for (cIndex = 0; cIndex < lReinsert; ++cIndex) + { + m_pTree->insertData_impl( + reinsertlen[cIndex], reinsertdata[cIndex], + *(reinsertmbr[cIndex]), reinsertid[cIndex], + m_level, overflowTable); + } + + delete[] reinsertdata; + delete[] reinsertmbr; + delete[] reinsertid; + delete[] reinsertlen; + + return true; + } + else + { + NodePtr n; + NodePtr nn; + split(dataLength, pData, mbr, id, n, nn); + + if (pathBuffer.empty()) + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = -1; + nn->m_identifier = -1; + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + assert(n->m_nodeMBR.containsRegionAfterTime(n->m_nodeMBR.m_startTime, *(n->m_ptrMBR[cChild])) == true); + } + for (uint32_t cChild = 0; cChild < nn->m_children; ++cChild) + { + assert(nn->m_nodeMBR.containsRegionAfterTime(nn->m_nodeMBR.m_startTime, *(nn->m_ptrMBR[cChild])) == true); + } +#endif + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + NodePtr ptrR = m_pTree->m_indexPool.acquire(); + if (ptrR.get() == 0) + { + ptrR = NodePtr(new Index(m_pTree, m_pTree->m_rootID, m_level + 1), &(m_pTree->m_indexPool)); + } + else + { + //ptrR->m_pTree = m_pTree; + ptrR->m_identifier = m_pTree->m_rootID; + ptrR->m_level = m_level + 1; + ptrR->m_nodeMBR = m_pTree->m_infiniteRegion; + } + + ptrR->insertEntry(0, 0, n->m_nodeMBR, n->m_identifier); + ptrR->insertEntry(0, 0, nn->m_nodeMBR, nn->m_identifier); + + m_pTree->writeNode(ptrR.get()); + + m_pTree->m_stats.m_nodesInLevel[m_level] = 2; + m_pTree->m_stats.m_nodesInLevel.push_back(1); + m_pTree->m_stats.m_treeHeight = m_level + 2; + } + else + { + n->m_level = m_level; + nn->m_level = m_level; + n->m_identifier = m_identifier; + nn->m_identifier = -1; + +#ifndef NDEBUG + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + assert(n->m_nodeMBR.containsRegionAfterTime(n->m_nodeMBR.m_startTime, *(n->m_ptrMBR[cChild])) == true); + } + for (uint32_t cChild = 0; cChild < nn->m_children; ++cChild) + { + assert(nn->m_nodeMBR.containsRegionAfterTime(nn->m_nodeMBR.m_startTime, *(nn->m_ptrMBR[cChild])) == true); + } +#endif + + m_pTree->writeNode(n.get()); + m_pTree->writeNode(nn.get()); + + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrN = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrN.get()); + p->adjustTree(n.get(), nn.get(), pathBuffer, overflowTable); + } + + return true; + } +} + +void Node::reinsertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep) +{ + ReinsertEntry** v = new ReinsertEntry*[m_capacity + 1]; + + m_pDataLength[m_children] = dataLength; + m_pData[m_children] = pData; + m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_children]) = mbr; + m_pIdentifier[m_children] = id; + + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + for (uint32_t cChild = 0; cChild < m_capacity + 1; ++cChild) + { + try + { + v[cChild] = new ReinsertEntry(cChild, 0.0); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete v[i]; + delete[] v; + throw; + } + + v[cChild]->m_dist = m_nodeMBR.getCenterDistanceInTime(ivT, *(m_ptrMBR[cChild])); + } + + // sort by increasing order of distances. + ::qsort(v, m_capacity + 1, sizeof(ReinsertEntry*), ReinsertEntry::compareReinsertEntry); + + uint32_t cReinsert = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_reinsertFactor)); + + uint32_t cCount; + + for (cCount = 0; cCount < cReinsert; ++cCount) + { + reinsert.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + for (cCount = cReinsert; cCount < m_capacity + 1; ++cCount) + { + keep.push_back(v[cCount]->m_index); + delete v[cCount]; + } + + delete[] v; +} + +/* +void Node::rtreeSplit(uint32_t dataLength, byte* pData, Region& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + uint32_t cChild; + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + // use this mask array for marking visited entries. + byte* mask = new byte[m_capacity + 1]; + bzero(mask, m_capacity + 1); + + // insert new data in the node for easier manipulation. Data arrays are always + // by one larger than node capacity. + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + + // initialize each group with the seed entries. + uint32_t seed1, seed2; + pickSeeds(seed1, seed2); + + group1.push_back(seed1); + group2.push_back(seed2); + + mask[seed1] = 1; + mask[seed2] = 1; + + // find MBR of each group. + RegionPtr mbr1 = m_pTree->m_regionPool.acquire(); + *mbr1 = *(m_ptrMBR[seed1]); + RegionPtr mbr2 = m_pTree->m_regionPool.acquire(); + *mbr2 = *(m_ptrMBR[seed2]); + + // count how many entries are left unchecked (exclude the seeds here.) + uint32_t cRemaining = m_capacity + 1 - 2; + + while (cRemaining > 0) + { + if (minimumLoad - group1.size() == cRemaining) + { + // all remaining entries must be assigned to group1 to comply with minimun load requirement. + for (cChild = 0; cChild < m_capacity + 1; ++cChild) + { + if (mask[cChild] == 0) + { + group1.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else if (minimumLoad - group2.size() == cRemaining) + { + // all remaining entries must be assigned to group2 to comply with minimun load requirement. + for (cChild = 0; cChild < m_capacity + 1; ++cChild) + { + if (mask[cChild] == 0) + { + group2.push_back(cChild); + mask[cChild] = 1; + --cRemaining; + } + } + } + else + { + // For all remaining entries compute the difference of the cost of grouping an + // entry in either group. When done, choose the entry that yielded the maximum + // difference. In case of linear split, select any entry (e.g. the first one.) + uint32_t sel; + double md1 = 0.0, md2 = 0.0; + double m = -std::numeric_limits<double>::max(); + double d1, d2, d; + double a1 = mbr1->getArea(); + double a2 = mbr2->getArea(); + + RegionPtr a = m_pTree->m_regionPool.acquire(); + RegionPtr b = m_pTree->m_regionPool.acquire(); + + for (cChild = 0; cChild < m_capacity + 1; ++cChild) + { + if (mask[cChild] == 0) + { + mbr1->getCombinedRegion(*a, *(m_ptrMBR[cChild])); + d1 = a->getArea() - a1; + mbr2->getCombinedRegion(*b, *(m_ptrMBR[cChild])); + d2 = b->getArea() - a2; + d = std::abs(d1 - d2); + + if (d > m) + { + m = d; + md1 = d1; md2 = d2; + sel = cChild; + if (m_pTree->m_treeVariant== RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR) break; + } + } + } + + // determine the group where we should add the new entry. + int32_t group = -1; + + if (md1 < md2) + { + group1.push_back(sel); + group = 1; + } + else if (md2 < md1) + { + group2.push_back(sel); + group = 2; + } + else if (a1 < a2) + { + group1.push_back(sel); + group = 1; + } + else if (a2 < a1) + { + group2.push_back(sel); + group = 2; + } + else if (group1.size() < group2.size()) + { + group1.push_back(sel); + group = 1; + } + else if (group2.size() < group1.size()) + { + group2.push_back(sel); + group = 2; + } + else + { + group1.push_back(sel); + group = 1; + } + mask[sel] = 1; + --cRemaining; + if (group == 1) + { + mbr1->combineRegion(*(m_ptrMBR[sel])); + } + else + { + mbr2->combineRegion(*(m_ptrMBR[sel])); + } + } + } + + delete[] mask; +} +*/ + +void Node::rstarSplit(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2) +{ + RstarSplitEntry** dataLow = 0; + RstarSplitEntry** dataHigh = 0; + RstarSplitEntry** dataVLow = 0; + RstarSplitEntry** dataVHigh = 0; + + try + { + dataLow = new RstarSplitEntry*[m_capacity + 1]; + dataHigh = new RstarSplitEntry*[m_capacity + 1]; + dataVLow = new RstarSplitEntry*[m_capacity + 1]; + dataVHigh = new RstarSplitEntry*[m_capacity + 1]; + } + catch (...) + { + delete[] dataLow; + delete[] dataHigh; + delete[] dataVLow; + delete[] dataVHigh; + throw; + } + + m_pDataLength[m_capacity] = dataLength; + m_pData[m_capacity] = pData; + m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire(); + *(m_ptrMBR[m_capacity]) = mbr; + m_pIdentifier[m_capacity] = id; + + uint32_t nodeSPF = static_cast<uint32_t>(std::floor((m_capacity + 1) * m_pTree->m_splitDistributionFactor)); + uint32_t splitDistribution = (m_capacity + 1) - (2 * nodeSPF) + 2; + + Tools::Interval ivT(m_pTree->m_currentTime, m_pTree->m_currentTime + m_pTree->m_horizon); + + uint32_t cChild = 0, cDim, cIndex; + + for (cChild = 0; cChild <= m_capacity; ++cChild) + { + try + { + dataLow[cChild] = new RstarSplitEntry(m_ptrMBR[cChild].get(), cChild, 0); + } + catch (...) + { + for (uint32_t i = 0; i < cChild; ++i) delete dataLow[i]; + delete[] dataLow; + delete[] dataHigh; + throw; + } + + dataHigh[cChild] = dataLow[cChild]; + dataVLow[cChild] = dataLow[cChild]; + dataVHigh[cChild] = dataLow[cChild]; + } + + double minimumMargin = std::numeric_limits<double>::max(); + uint32_t splitAxis = std::numeric_limits<uint32_t>::max(); + uint32_t sortOrder = std::numeric_limits<uint32_t>::max(); + + // chooseSplitAxis. + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow); + ::qsort(dataHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh); + ::qsort(dataVLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVLow); + ::qsort(dataVHigh, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVHigh); + + // calculate sum of margins and overlap for all distributions. + double marginl = 0.0; + double marginh = 0.0; + double marginvl = 0.0; + double marginvh = 0.0; + + MovingRegion bbl1, bbl2, bbh1, bbh2; + MovingRegion bbvl1, bbvl2, bbvh1, bbvh2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bbl1 = *(dataLow[0]->m_pRegion); + bbh1 = *(dataHigh[0]->m_pRegion); + bbvl1 = *(dataVLow[0]->m_pRegion); + bbvh1 = *(dataVHigh[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bbl1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + bbh1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataHigh[cIndex]->m_pRegion)); + bbvl1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVLow[cIndex]->m_pRegion)); + bbvh1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVHigh[cIndex]->m_pRegion)); + } + + bbl2 = *(dataLow[l]->m_pRegion); + bbh2 = *(dataHigh[l]->m_pRegion); + bbvl2 = *(dataVLow[l]->m_pRegion); + bbvh2 = *(dataVHigh[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bbl2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + bbh2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataHigh[cIndex]->m_pRegion)); + bbvl2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVLow[cIndex]->m_pRegion)); + bbvh2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataVHigh[cIndex]->m_pRegion)); + } + + marginl += bbl1.getProjectedSurfaceAreaInTime(ivT) + bbl2.getProjectedSurfaceAreaInTime(ivT); + marginh += bbh1.getProjectedSurfaceAreaInTime(ivT) + bbh2.getProjectedSurfaceAreaInTime(ivT); + marginvl += bbvl1.getProjectedSurfaceAreaInTime(ivT) + bbvl2.getProjectedSurfaceAreaInTime(ivT); + marginvh += bbvh1.getProjectedSurfaceAreaInTime(ivT) + bbvh2.getProjectedSurfaceAreaInTime(ivT); + } // for (cChild) + + double margin = std::min(std::min(marginl, marginh), std::min(marginvl, marginvh)); + + // keep minimum margin as split axis. + if (margin < minimumMargin) + { + minimumMargin = margin; + splitAxis = cDim; + if (marginl < marginh && marginl < marginvl && marginl < marginvh) sortOrder = 0; + else if (marginh < marginl && marginh < marginvl && marginh < marginvh) sortOrder = 1; + else if (marginvl < marginl && marginvl < marginh && marginvl < marginvh) sortOrder = 2; + else if (marginvh < marginl && marginvh < marginh && marginvh < marginvl) sortOrder = 3; + } + + // increase the dimension according to which the data entries should be sorted. + for (cChild = 0; cChild <= m_capacity; ++cChild) + { + dataLow[cChild]->m_sortDim = cDim + 1; + } + } // for (cDim) + + for (cChild = 0; cChild <= m_capacity; ++cChild) + { + dataLow[cChild]->m_sortDim = splitAxis; + } + + if (sortOrder == 0) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareLow); + else if (sortOrder == 1) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareHigh); + else if (sortOrder == 2) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVLow); + else if (sortOrder == 3) + ::qsort(dataLow, m_capacity + 1, sizeof(RstarSplitEntry*), RstarSplitEntry::compareVHigh); + + double ma = std::numeric_limits<double>::max(); + double mo = std::numeric_limits<double>::max(); + uint32_t splitPoint = std::numeric_limits<uint32_t>::max(); + + MovingRegion bb1, bb2; + + for (cChild = 1; cChild <= splitDistribution; ++cChild) + { + uint32_t l = nodeSPF - 1 + cChild; + + bb1 = *(dataLow[0]->m_pRegion); + + for (cIndex = 1; cIndex < l; ++cIndex) + { + bb1.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + } + + bb2 = *(dataLow[l]->m_pRegion); + + for (cIndex = l + 1; cIndex <= m_capacity; ++cIndex) + { + bb2.combineRegionAfterTime(m_pTree->m_currentTime, *(dataLow[cIndex]->m_pRegion)); + } + + double o = bb1.getIntersectingAreaInTime(ivT, bb2); + + if (o < mo) + { + splitPoint = cChild; + mo = o; + ma = bb1.getAreaInTime(ivT) + bb2.getAreaInTime(ivT); + } + else if (o == mo) + { + double a = bb1.getAreaInTime(ivT) + bb2.getAreaInTime(ivT); + + if (a < ma) + { + splitPoint = cChild; + ma = a; + } + } + } // for (cChild) + + uint32_t l1 = nodeSPF - 1 + splitPoint; + + for (cIndex = 0; cIndex < l1; ++cIndex) + { + group1.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + for (cIndex = l1; cIndex <= m_capacity; ++cIndex) + { + group2.push_back(dataLow[cIndex]->m_index); + delete dataLow[cIndex]; + } + + delete[] dataLow; + delete[] dataHigh; + delete[] dataVLow; + delete[] dataVHigh; +} + +/* +void Node::pickSeeds(uint32_t& index1, uint32_t& index2) +{ + double separation = -std::numeric_limits<double>::max(); + double inefficiency = -std::numeric_limits<double>::max(); + uint32_t cDim, cChild, cIndex; + + switch (m_pTree->m_treeVariant) + { + case RV_LINEAR: + case RV_RSTAR: + for (cDim = 0; cDim < m_pTree->m_dimension; ++cDim) + { + double leastLower = m_ptrMBR[0]->m_pLow[cDim]; + double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim]; + uint32_t greatestLower = 0; + uint32_t leastUpper = 0; + double width; + + for (cChild = 1; cChild <= m_capacity; ++cChild) + { + if (m_ptrMBR[cChild]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim]) greatestLower = cChild; + if (m_ptrMBR[cChild]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim]) leastUpper = cChild; + + leastLower = std::min(m_ptrMBR[cChild]->m_pLow[cDim], leastLower); + greatestUpper = std::max(m_ptrMBR[cChild]->m_pHigh[cDim], greatestUpper); + } + + width = greatestUpper - leastLower; + if (width <= 0) width = 1; + + double f = (m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim]) / width; + + if (f > separation) + { + index1 = leastUpper; + index2 = greatestLower; + separation = f; + } + } // for (cDim) + + if (index1 == index2) + { + if (index2 == 0) ++index2; + else --index2; + } + + break; + case RV_QUADRATIC: + // for each pair of Regions (account for overflow Region too!) + for (cChild = 0; cChild < m_capacity; ++cChild) + { + double a = m_ptrMBR[cChild]->getArea(); + + for (cIndex = cChild + 1; cIndex <= m_capacity; ++cIndex) + { + // get the combined MBR of those two entries. + Region r; + m_ptrMBR[cChild]->getCombinedRegion(r, *(m_ptrMBR[cIndex])); + + // find the inefficiency of grouping these entries together. + double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea(); + + if (d > inefficiency) + { + inefficiency = d; + index1 = cChild; + index2 = cIndex; + } + } // for (cIndex) + } // for (cChild) + + break; + default: + throw Tools::NotSupportedException("Node::pickSeeds: Tree variant not supported."); + } +} +*/ + +void Node::condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis) +{ + uint32_t minimumLoad = static_cast<uint32_t>(std::floor(m_capacity * m_pTree->m_fillFactor)); + + if (pathBuffer.empty()) + { + // eliminate root if it has only one child. + if (m_level != 0 && m_children == 1) + { + NodePtr ptrN = m_pTree->readNode(m_pIdentifier[0]); + m_pTree->deleteNode(ptrN.get()); + ptrN->m_identifier = m_pTree->m_rootID; + m_pTree->writeNode(ptrN.get()); + + m_pTree->m_stats.m_nodesInLevel.pop_back(); + m_pTree->m_stats.m_treeHeight -= 1; + // HACK: pending deleteNode for deleted child will decrease nodesInLevel, later on. + m_pTree->m_stats.m_nodesInLevel[m_pTree->m_stats.m_treeHeight - 1] = 2; + } + } + else + { + id_type cParent = pathBuffer.top(); pathBuffer.pop(); + NodePtr ptrParent = m_pTree->readNode(cParent); + Index* p = static_cast<Index*>(ptrParent.get()); + + // find the entry in the parent, that points to this node. + uint32_t child; + + for (child = 0; child != p->m_children; ++child) + { + if (p->m_pIdentifier[child] == m_identifier) break; + } + + if (m_children < minimumLoad) + { + // used space less than the minimum + // 1. eliminate node entry from the parent. deleteEntry will fix the parent's MBR. + p->deleteEntry(child); + // 2. add this node to the stack in order to reinsert its entries. + toReinsert.push(ptrThis); + } + else + { + // adjust the entry in 'p' to contain the new bounding region of this node. + *(p->m_ptrMBR[child]) = m_nodeMBR; + + // global recalculation necessary since the MBR can only shrink in size, + // due to data removal. + //if (m_pTree->m_bTightMBRs) + //{ + + p->m_nodeMBR.m_startTime = m_pTree->m_currentTime; + + for (uint32_t cDim = 0; cDim < p->m_nodeMBR.m_dimension; ++cDim) + { + p->m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pVLow[cDim] = std::numeric_limits<double>::max(); + p->m_nodeMBR.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + p->m_nodeMBR.m_pLow[cDim] = std::min(p->m_nodeMBR.m_pLow[cDim], p->m_ptrMBR[cChild]->getExtrapolatedLow(cDim, m_pTree->m_currentTime)); + p->m_nodeMBR.m_pHigh[cDim] = std::max(p->m_nodeMBR.m_pHigh[cDim], p->m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, m_pTree->m_currentTime)); + p->m_nodeMBR.m_pVLow[cDim] = std::min(p->m_nodeMBR.m_pVLow[cDim], p->m_ptrMBR[cChild]->m_pVLow[cDim]); + p->m_nodeMBR.m_pVHigh[cDim] = std::max(p->m_nodeMBR.m_pVHigh[cDim], p->m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + p->m_nodeMBR.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + p->m_nodeMBR.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + //} + } + + // write parent node back to storage. + m_pTree->writeNode(p); + + p->condenseTree(toReinsert, pathBuffer, ptrParent); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Node.h b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Node.h new file mode 100644 index 000000000..6cf5d98a0 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Node.h @@ -0,0 +1,200 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class TPRTree; + class Leaf; + class Index; + class Node; + + typedef Tools::PoolPointer<Node> NodePtr; + + class Node : public SpatialIndex::INode + { + public: + virtual ~Node(); + + // + // Tools::IObject interface + // + virtual Tools::IObject* clone(); + + // + // Tools::ISerializable interface + // + virtual uint32_t getByteArraySize(); + virtual void loadFromByteArray(const byte* data); + virtual void storeToByteArray(byte** data, uint32_t& len); + + // + // SpatialIndex::IEntry interface + // + virtual id_type getIdentifier() const; + virtual void getShape(IShape** out) const; + + // + // SpatialIndex::INode interface + // + virtual uint32_t getChildrenCount() const; + virtual id_type getChildIdentifier(uint32_t index) const; + virtual void getChildShape(uint32_t index, IShape** out) const; + virtual void getChildData(uint32_t index, uint32_t& length, byte** data) const; + virtual uint32_t getLevel() const; + virtual bool isIndex() const; + virtual bool isLeaf() const; + + private: + Node(); + Node(TPRTree* pTree, id_type id, uint32_t level, uint32_t capacity); + + virtual Node& operator=(const Node&); + + virtual bool insertEntry(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id); + virtual void deleteEntry(uint32_t index); + + virtual bool insertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer, byte* overflowTable); + virtual void reinsertData(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& reinsert, std::vector<uint32_t>& keep); + + virtual void rstarSplit(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, std::vector<uint32_t>& group1, std::vector<uint32_t>& group2); + + virtual void condenseTree(std::stack<NodePtr>& toReinsert, std::stack<id_type>& pathBuffer, NodePtr& ptrThis); + + virtual NodePtr chooseSubtree(const MovingRegion& mbr, uint32_t level, std::stack<id_type>& pathBuffer) = 0; + virtual NodePtr findLeaf(const MovingRegion& mbr, id_type id, std::stack<id_type>& pathBuffer) = 0; + + virtual void split(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, NodePtr& left, NodePtr& right) = 0; + + TPRTree* m_pTree; + // Parent of all nodes. + + uint32_t m_level; + // The level of the node in the tree. + // Leaves are always at level 0. + + id_type m_identifier; + // The unique ID of this node. + + uint32_t m_children; + // The number of children pointed by this node. + + uint32_t m_capacity; + // Specifies the node capacity. + + MovingRegion m_nodeMBR; + // The minimum bounding region enclosing all data contained in the node. + + byte** m_pData; + // The data stored in the node. + + MovingRegionPtr* m_ptrMBR; + // The corresponding data MBRs. + + id_type* m_pIdentifier; + // The corresponding data identifiers. + + uint32_t* m_pDataLength; + + uint32_t m_totalDataLength; + + class RstarSplitEntry + { + public: + MovingRegion* m_pRegion; + uint32_t m_index; + uint32_t m_sortDim; + + RstarSplitEntry(MovingRegion* pr, uint32_t index, uint32_t dimension) + : m_pRegion(pr), m_index(index), m_sortDim(dimension) {} + + static int compareLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] < pe2->m_pRegion->m_pLow[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pLow[pe1->m_sortDim] > pe2->m_pRegion->m_pLow[pe1->m_sortDim]) return 1; + return 0; + } + + static int compareHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pHigh[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pHigh[pe1->m_sortDim]) return 1; + return 0; + } + + static int compareVLow(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pVLow[pe1->m_sortDim] < pe2->m_pRegion->m_pVLow[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pVLow[pe1->m_sortDim] > pe2->m_pRegion->m_pVLow[pe1->m_sortDim]) return 1; + return 0; + } + + static int compareVHigh(const void* pv1, const void* pv2) + { + RstarSplitEntry* pe1 = * (RstarSplitEntry**) pv1; + RstarSplitEntry* pe2 = * (RstarSplitEntry**) pv2; + + if (pe1->m_pRegion->m_pVHigh[pe1->m_sortDim] < pe2->m_pRegion->m_pVHigh[pe1->m_sortDim]) return -1; + if (pe1->m_pRegion->m_pVHigh[pe1->m_sortDim] > pe2->m_pRegion->m_pVHigh[pe1->m_sortDim]) return 1; + return 0; + } + }; // RstarSplitEntry + + class ReinsertEntry + { + public: + uint32_t m_index; + double m_dist; + + ReinsertEntry(uint32_t index, double dist) : m_index(index), m_dist(dist) {} + + static int compareReinsertEntry(const void* pv1, const void* pv2) + { + ReinsertEntry* pe1 = * (ReinsertEntry**) pv1; + ReinsertEntry* pe2 = * (ReinsertEntry**) pv2; + + if (pe1->m_dist < pe2->m_dist) return -1; + if (pe1->m_dist > pe2->m_dist) return 1; + return 0; + } + }; // ReinsertEntry + + // Needed to access protected members without having to cast from Node. + // It is more efficient than using member functions to access protected members. + friend class TPRTree; + friend class Leaf; + friend class Index; + friend class Tools::PointerPool<Node>; + }; // Node + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/PointerPoolNode.h b/sci-libs/libspatialindex/svn/trunk/src/tprtree/PointerPoolNode.h new file mode 100644 index 000000000..8c026fbe3 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/PointerPoolNode.h @@ -0,0 +1,133 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Node.h" + +namespace Tools +{ + template<> class PointerPool<TPRTree::Node> + { + public: + explicit PointerPool(uint32_t capacity) : m_capacity(capacity) + { + #ifndef NDEBUG + m_hits = 0; + m_misses = 0; + m_pointerCount = 0; + #endif + } + + ~PointerPool() + { + assert(m_pool.size() <= m_capacity); + + while (! m_pool.empty()) + { + TPRTree::Node* x = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + --m_pointerCount; + #endif + delete x; + } + + #ifndef NDEBUG + std::cerr << "Lost pointers: " << m_pointerCount << std::endl; + #endif + } + + PoolPointer<TPRTree::Node> acquire() + { + if (! m_pool.empty()) + { + TPRTree::Node* p = m_pool.top(); m_pool.pop(); + #ifndef NDEBUG + ++m_hits; + #endif + + return PoolPointer<TPRTree::Node>(p, this); + } + #ifndef NDEBUG + else + { + // fixme: well sort of... + ++m_pointerCount; + ++m_misses; + } + #endif + + return PoolPointer<TPRTree::Node>(); + } + + void release(TPRTree::Node* p) + { + if (p != 0) + { + if (m_pool.size() < m_capacity) + { + if (p->m_pData != 0) + { + for (uint32_t cChild = 0; cChild < p->m_children; ++cChild) + { + if (p->m_pData[cChild] != 0) delete[] p->m_pData[cChild]; + } + } + + p->m_level = 0; + p->m_identifier = -1; + p->m_children = 0; + p->m_totalDataLength = 0; + + m_pool.push(p); + } + else + { + #ifndef NDEBUG + --m_pointerCount; + #endif + delete p; + } + + assert(m_pool.size() <= m_capacity); + } + } + + uint32_t getCapacity() const { return m_capacity; } + void setCapacity(uint32_t c) + { + assert (c >= 0); + m_capacity = c; + } + + protected: + uint32_t m_capacity; + std::stack<TPRTree::Node*> m_pool; + + #ifndef NDEBUG + public: + uint64_t m_hits; + uint64_t m_misses; + uint64_t m_pointerCount; + #endif + }; +} + diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Statistics.cc b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Statistics.cc new file mode 100644 index 000000000..d2031d4db --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Statistics.cc @@ -0,0 +1,171 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Statistics.h" + +using namespace SpatialIndex::TPRTree; + +Statistics::Statistics() +{ + reset(); +} + +Statistics::Statistics(const Statistics& s) +{ + m_reads = s.m_reads; + m_writes = s.m_writes; + m_splits = s.m_splits; + m_hits = s.m_hits; + m_misses = s.m_misses; + m_nodes = s.m_nodes; + m_adjustments = s.m_adjustments; + m_queryResults = s.m_queryResults; + m_data = s.m_data; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; +} + +Statistics::~Statistics() +{ +} + +Statistics& Statistics::operator=(const Statistics& s) +{ + if (this != &s) + { + m_reads = s.m_reads; + m_writes = s.m_writes; + m_splits = s.m_splits; + m_hits = s.m_hits; + m_misses = s.m_misses; + m_nodes = s.m_nodes; + m_adjustments = s.m_adjustments; + m_queryResults = s.m_queryResults; + m_data = s.m_data; + m_treeHeight = s.m_treeHeight; + m_nodesInLevel = s.m_nodesInLevel; + } + + return *this; +} + +uint64_t Statistics::getReads() const +{ + return m_reads; +} + +uint64_t Statistics::getWrites() const +{ + return m_writes; +} + +uint32_t Statistics::getNumberOfNodes() const +{ + return m_nodes; +} + +uint64_t Statistics::getNumberOfData() const +{ + return m_data; +} + +uint64_t Statistics::getSplits() const +{ + return m_splits; +} + +uint64_t Statistics::getHits() const +{ + return m_hits; +} + +uint64_t Statistics::getMisses() const +{ + return m_misses; +} + +uint64_t Statistics::getAdjustments() const +{ + return m_adjustments; +} + +uint64_t Statistics::getQueryResults() const +{ + return m_queryResults; +} + +uint32_t Statistics::getTreeHeight() const +{ + return m_treeHeight; +} + +uint32_t Statistics::getNumberOfNodesInLevel(uint32_t l) const +{ + uint32_t cNodes; + try + { + cNodes = m_nodesInLevel.at(l); + } + catch (...) + { + throw Tools::IndexOutOfBoundsException(l); + } + + return cNodes; +} + +void Statistics::reset() +{ + m_reads = 0; + m_writes = 0; + m_splits = 0; + m_hits = 0; + m_misses = 0; + m_nodes = 0; + m_adjustments = 0; + m_queryResults = 0; + m_data = 0; + m_treeHeight = 0; + m_nodesInLevel.clear(); +} + +std::ostream& SpatialIndex::TPRTree::operator<<(std::ostream& os, const Statistics& s) +{ + os << "Reads: " << s.m_reads << std::endl + << "Writes: " << s.m_writes << std::endl + << "Hits: " << s.m_hits << std::endl + << "Misses: " << s.m_misses << std::endl + << "Tree height: " << s.m_treeHeight << std::endl + << "Number of data: " << s.m_data << std::endl + << "Number of nodes: " << s.m_nodes << std::endl; + + for (uint32_t cLevel = 0; cLevel < s.m_treeHeight; ++cLevel) + { + os << "Level " << cLevel << " pages: " << s.m_nodesInLevel[cLevel] << std::endl; + } + + os << "Splits: " << s.m_splits << std::endl + << "Adjustments: " << s.m_adjustments << std::endl + << "Query results: " << s.m_queryResults << std::endl; + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/Statistics.h b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Statistics.h new file mode 100644 index 000000000..44b707c30 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/Statistics.h @@ -0,0 +1,93 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +namespace SpatialIndex +{ + namespace TPRTree + { + class TPRTree; + class Node; + class Leaf; + class Index; + + class Statistics : public SpatialIndex::IStatistics + { + public: + Statistics(); + Statistics(const Statistics&); + virtual ~Statistics(); + Statistics& operator=(const Statistics&); + + // + // IStatistics interface + // + virtual uint64_t getReads() const; + virtual uint64_t getWrites() const; + virtual uint32_t getNumberOfNodes() const; + virtual uint64_t getNumberOfData() const; + + virtual uint64_t getSplits() const; + virtual uint64_t getHits() const; + virtual uint64_t getMisses() const; + virtual uint64_t getAdjustments() const; + virtual uint64_t getQueryResults() const; + virtual uint32_t getTreeHeight() const; + virtual uint32_t getNumberOfNodesInLevel(uint32_t l) const; + + private: + void reset(); + + uint64_t m_reads; + + uint64_t m_writes; + + uint64_t m_splits; + + uint64_t m_hits; + + uint64_t m_misses; + + uint32_t m_nodes; + + uint64_t m_adjustments; + + uint64_t m_queryResults; + + uint64_t m_data; + + uint32_t m_treeHeight; + + std::vector<uint32_t> m_nodesInLevel; + + friend class TPRTree; + friend class Node; + friend class Index; + friend class Leaf; + friend class BulkLoader; + + friend std::ostream& operator<<(std::ostream& os, const Statistics& s); + }; // Statistics + + std::ostream& operator<<(std::ostream& os, const Statistics& s); + } +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/TPRTree.cc b/sci-libs/libspatialindex/svn/trunk/src/tprtree/TPRTree.cc new file mode 100644 index 000000000..16b8f9c54 --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/TPRTree.cc @@ -0,0 +1,1352 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#include <limits> + +#include "../spatialindex/SpatialIndexImpl.h" +#include "Node.h" +#include "Leaf.h" +#include "Index.h" +#include "TPRTree.h" + +#include <cstring> + +using namespace SpatialIndex::TPRTree; + +SpatialIndex::TPRTree::Data::Data(uint32_t len, byte* pData, MovingRegion& r, id_type id) + : m_id(id), m_region(r), m_pData(0), m_dataLength(len) +{ + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, pData, m_dataLength); + } +} + +SpatialIndex::TPRTree::Data::~Data() +{ + delete[] m_pData; +} + +SpatialIndex::TPRTree::Data* SpatialIndex::TPRTree::Data::clone() +{ + return new Data(m_dataLength, m_pData, m_region, m_id); +} + +SpatialIndex::id_type SpatialIndex::TPRTree::Data::getIdentifier() const +{ + return m_id; +} + +void SpatialIndex::TPRTree::Data::getShape(IShape** out) const +{ + *out = new MovingRegion(m_region); +} + +void SpatialIndex::TPRTree::Data::getData(uint32_t& len, byte** data) const +{ + len = m_dataLength; + *data = 0; + + if (m_dataLength > 0) + { + *data = new byte[m_dataLength]; + memcpy(*data, m_pData, m_dataLength); + } +} + +uint32_t SpatialIndex::TPRTree::Data::getByteArraySize() +{ + return + sizeof(id_type) + + sizeof(uint32_t) + + m_dataLength + + m_region.getByteArraySize(); +} + +void SpatialIndex::TPRTree::Data::loadFromByteArray(const byte* ptr) +{ + memcpy(&m_id, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + + delete[] m_pData; + m_pData = 0; + + memcpy(&m_dataLength, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + m_pData = new byte[m_dataLength]; + memcpy(m_pData, ptr, m_dataLength); + ptr += m_dataLength; + } + + m_region.loadFromByteArray(ptr); +} + +void SpatialIndex::TPRTree::Data::storeToByteArray(byte** data, uint32_t& len) +{ + // it is thread safe this way. + uint32_t regionsize; + byte* regiondata = 0; + m_region.storeToByteArray(®iondata, regionsize); + + len = sizeof(id_type) + sizeof(uint32_t) + m_dataLength + regionsize; + + *data = new byte[len]; + byte* ptr = *data; + + memcpy(ptr, &m_id, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_dataLength, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + if (m_dataLength > 0) + { + memcpy(ptr, m_pData, m_dataLength); + ptr += m_dataLength; + } + + memcpy(ptr, regiondata, regionsize); + delete[] regiondata; + // ptr += regionsize; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::TPRTree::returnTPRTree(SpatialIndex::IStorageManager& sm, Tools::PropertySet& ps) +{ + SpatialIndex::ISpatialIndex* si = new SpatialIndex::TPRTree::TPRTree(sm, ps); + return si; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::TPRTree::createNewTPRTree( + SpatialIndex::IStorageManager& sm, + double fillFactor, + uint32_t indexCapacity, + uint32_t leafCapacity, + uint32_t dimension, + TPRTreeVariant rv, + double horizon, + id_type& indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = fillFactor; + ps.setProperty("FillFactor", var); + + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = horizon; + ps.setProperty("Horizon", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = indexCapacity; + ps.setProperty("IndexCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = leafCapacity; + ps.setProperty("LeafCapacity", var); + + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = dimension; + ps.setProperty("Dimension", var); + + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = rv; + ps.setProperty("TreeVariant", var); + + ISpatialIndex* ret = returnTPRTree(sm, ps); + + var.m_varType = Tools::VT_LONGLONG; + var = ps.getProperty("IndexIdentifier"); + indexIdentifier = var.m_val.llVal; + + return ret; +} + +SpatialIndex::ISpatialIndex* SpatialIndex::TPRTree::loadTPRTree(IStorageManager& sm, id_type indexIdentifier) +{ + Tools::Variant var; + Tools::PropertySet ps; + + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = indexIdentifier; + ps.setProperty("IndexIdentifier", var); + + return returnTPRTree(sm, ps); +} + +SpatialIndex::TPRTree::TPRTree::TPRTree(IStorageManager& sm, Tools::PropertySet& ps) : + m_pStorageManager(&sm), + m_rootID(StorageManager::NewPage), + m_headerID(StorageManager::NewPage), + m_treeVariant(TPRV_RSTAR), + m_fillFactor(0.7), + m_indexCapacity(100), + m_leafCapacity(100), + m_nearMinimumOverlapFactor(32), + m_splitDistributionFactor(0.4), + m_reinsertFactor(0.3), + m_dimension(2), + m_bTightMBRs(true), + m_currentTime(0.0), + m_horizon(20.0), + m_pointPool(500), + m_regionPool(1000), + m_indexPool(100), + m_leafPool(100) +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_init(&m_rwLock, NULL); +#else + m_rwLock = false; +#endif + + Tools::Variant var = ps.getProperty("IndexIdentifier"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType == Tools::VT_LONGLONG) m_headerID = var.m_val.llVal; + else if (var.m_varType == Tools::VT_LONG) m_headerID = var.m_val.lVal; + // for backward compatibility only. + else throw Tools::IllegalArgumentException("TPRTree: Property IndexIdentifier must be Tools::VT_LONGLONG"); + + initOld(ps); + } + else + { + initNew(ps); + var.m_varType = Tools::VT_LONGLONG; + var.m_val.llVal = m_headerID; + ps.setProperty("IndexIdentifier", var); + } +} + +SpatialIndex::TPRTree::TPRTree::~TPRTree() +{ +#ifdef HAVE_PTHREAD_H + pthread_rwlock_destroy(&m_rwLock); +#endif + + storeHeader(); +} + +// +// ISpatialIndex interface +// + +void SpatialIndex::TPRTree::TPRTree::insertData(uint32_t len, const byte* pData, const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + const IEvolvingShape* es = dynamic_cast<const IEvolvingShape*>(&shape); + if (es == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IEvolvingShape interface."); + const Tools::IInterval *pivI = dynamic_cast<const Tools::IInterval*>(&shape); + if (pivI == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IInterval interface."); + + if (pivI->getLowerBound() < m_currentTime) throw Tools::IllegalArgumentException("insertData: Shape start time is older than tree current time."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("insertData: cannot acquire an exclusive lock"); +#endif + + try + { + Region mbr; + shape.getMBR(mbr); + Region vbr; + es->getVMBR(vbr); + assert(mbr.m_dimension == vbr.m_dimension); + + MovingRegionPtr mr = m_regionPool.acquire(); + mr->makeDimension(mbr.m_dimension); + + memcpy(mr->m_pLow, mbr.m_pLow, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pHigh, mbr.m_pHigh, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVLow, vbr.m_pLow, vbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVHigh, vbr.m_pHigh, vbr.m_dimension * sizeof(double)); + mr->m_startTime = pivI->getLowerBound(); + mr->m_endTime = std::numeric_limits<double>::max(); + + byte* buffer = 0; + + if (len > 0) + { + buffer = new byte[len]; + memcpy(buffer, pData, len); + } + + m_currentTime = mr->m_startTime; + insertData_impl(len, buffer, *mr, id); + // the buffer is stored in the tree. Do not delete here. + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +// shape.m_startTime should be the time when the object was inserted initially. +// shape.m_endTime should be the time of the deletion (current time). +bool SpatialIndex::TPRTree::TPRTree::deleteData(const IShape& shape, id_type id) +{ + if (shape.getDimension() != m_dimension) throw Tools::IllegalArgumentException("insertData: Shape has the wrong number of dimensions."); + const IEvolvingShape* es = dynamic_cast<const IEvolvingShape*>(&shape); + if (es == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IEvolvingShape interface."); + const Tools::IInterval *pivI = dynamic_cast<const Tools::IInterval*>(&shape); + if (pivI == 0) throw Tools::IllegalArgumentException("insertData: Shape does not support the Tools::IInterval interface."); + +#ifdef HAVE_PTHREAD_H + Tools::ExclusiveLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("deleteData cannot acquire an exclusive lock"); +#endif + + try + { + Region mbr; + shape.getMBR(mbr); + Region vbr; + es->getVMBR(vbr); + assert(mbr.m_dimension == vbr.m_dimension); + + MovingRegionPtr mr = m_regionPool.acquire(); + mr->makeDimension(mbr.m_dimension); + + memcpy(mr->m_pLow, mbr.m_pLow, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pHigh, mbr.m_pHigh, mbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVLow, vbr.m_pLow, vbr.m_dimension * sizeof(double)); + memcpy(mr->m_pVHigh, vbr.m_pHigh, vbr.m_dimension * sizeof(double)); + mr->m_startTime = pivI->getLowerBound(); + mr->m_endTime = std::numeric_limits<double>::max(); + + m_currentTime = pivI->getUpperBound(); + bool ret = deleteData_impl(*mr, id); + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + + return ret; + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::containsWhatQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("containsWhatQuery: Shape has the wrong number of dimensions."); + rangeQuery(ContainmentQuery, query, v); +} + +void SpatialIndex::TPRTree::TPRTree::intersectsWithQuery(const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("intersectsWithQuery: Shape has the wrong number of dimensions."); + rangeQuery(IntersectionQuery, query, v); +} + +void SpatialIndex::TPRTree::TPRTree::pointLocationQuery(const Point& query, IVisitor& v) +{ + if (query.m_dimension != m_dimension) throw Tools::IllegalArgumentException("pointLocationQuery: Shape has the wrong number of dimensions."); + Region r(query, query); + rangeQuery(IntersectionQuery, r, v); +} + +void SpatialIndex::TPRTree::TPRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator& nnc) +{ + throw Tools::IllegalStateException("nearestNeighborQuery: not impelmented yet."); +} + +void SpatialIndex::TPRTree::TPRTree::nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v) +{ + if (query.getDimension() != m_dimension) throw Tools::IllegalArgumentException("nearestNeighborQuery: Shape has the wrong number of dimensions."); + NNComparator nnc; + nearestNeighborQuery(k, query, v, nnc); +} + +void SpatialIndex::TPRTree::TPRTree::selfJoinQuery(const IShape& query, IVisitor& v) +{ + throw Tools::IllegalStateException("selfJoinQuery: not impelmented yet."); +} + +void SpatialIndex::TPRTree::TPRTree::queryStrategy(IQueryStrategy& qs) +{ +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("queryStrategy: cannot acquire a shared lock"); +#endif + + id_type next = m_rootID; + bool hasNext = true; + + try + { + while (hasNext) + { + NodePtr n = readNode(next); + qs.getNextEntry(*n, next, hasNext); + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::getIndexProperties(Tools::PropertySet& out) const +{ + Tools::Variant var; + + // dimension + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_dimension; + out.setProperty("Dimension", var); + + // index capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexCapacity; + out.setProperty("IndexCapacity", var); + + // leaf capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafCapacity; + out.setProperty("LeafCapacity", var); + + // Tree variant + var.m_varType = Tools::VT_LONG; + var.m_val.lVal = m_treeVariant; + out.setProperty("TreeVariant", var); + + // fill factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_fillFactor; + out.setProperty("FillFactor", var); + + // horizon + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_horizon; + out.setProperty("Horizon", var); + + // near minimum overlap factor + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_nearMinimumOverlapFactor; + out.setProperty("NearMinimumOverlapFactor", var); + + // split distribution factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_splitDistributionFactor; + out.setProperty("SplitDistributionFactor", var); + + // reinsert factor + var.m_varType = Tools::VT_DOUBLE; + var.m_val.dblVal = m_reinsertFactor; + out.setProperty("ReinsertFactor", var); + + // tight MBRs + var.m_varType = Tools::VT_BOOL; + var.m_val.blVal = m_bTightMBRs; + out.setProperty("EnsureTightMBRs", var); + + // index pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_indexPool.getCapacity(); + out.setProperty("IndexPoolCapacity", var); + + // leaf pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_leafPool.getCapacity(); + out.setProperty("LeafPoolCapacity", var); + + // region pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_regionPool.getCapacity(); + out.setProperty("RegionPoolCapacity", var); + + // point pool capacity + var.m_varType = Tools::VT_ULONG; + var.m_val.ulVal = m_pointPool.getCapacity(); + out.setProperty("PointPoolCapacity", var); +} + +void SpatialIndex::TPRTree::TPRTree::addCommand(ICommand* pCommand, CommandType ct) +{ + switch (ct) + { + case CT_NODEREAD: + m_readNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEWRITE: + m_writeNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + case CT_NODEDELETE: + m_deleteNodeCommands.push_back(Tools::SmartPointer<ICommand>(pCommand)); + break; + } +} + +bool SpatialIndex::TPRTree::TPRTree::isIndexValid() +{ + bool ret = true; + + std::stack<ValidateEntry> st; + NodePtr root = readNode(m_rootID); + + if (root->m_level != m_stats.m_treeHeight - 1) + { + std::cerr << "Invalid tree height." << std::endl; + return false; + } + + std::map<uint32_t, uint32_t> nodesInLevel; + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(root->m_level, 1)); + + ValidateEntry e(root->m_nodeMBR, root); + st.push(e); + + while (! st.empty()) + { + e = st.top(); st.pop(); + + MovingRegion tmpRegion; + tmpRegion = m_infiniteRegion; + + // I have to rely on the parent information here, since none of the node's + // children might have a reference time equal to their parents (e.g., after + // a split). + tmpRegion.m_startTime = e.m_parentMBR.m_startTime; + + for (uint32_t cDim = 0; cDim < tmpRegion.m_dimension; ++cDim) + { + tmpRegion.m_pLow[cDim] = std::numeric_limits<double>::max(); + tmpRegion.m_pHigh[cDim] = -std::numeric_limits<double>::max(); + tmpRegion.m_pVLow[cDim] = std::numeric_limits<double>::max(); + tmpRegion.m_pVHigh[cDim] = -std::numeric_limits<double>::max(); + + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + tmpRegion.m_pLow[cDim] = std::min(tmpRegion.m_pLow[cDim], e.m_pNode->m_ptrMBR[cChild]->getExtrapolatedLow(cDim, tmpRegion.m_startTime)); + tmpRegion.m_pHigh[cDim] = std::max(tmpRegion.m_pHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->getExtrapolatedHigh(cDim, tmpRegion.m_startTime)); + tmpRegion.m_pVLow[cDim] = std::min(tmpRegion.m_pVLow[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pVLow[cDim]); + tmpRegion.m_pVHigh[cDim] = std::max(tmpRegion.m_pVHigh[cDim], e.m_pNode->m_ptrMBR[cChild]->m_pVHigh[cDim]); + } + tmpRegion.m_pLow[cDim] -= 2.0 * std::numeric_limits<double>::epsilon(); + tmpRegion.m_pHigh[cDim] += 2.0 * std::numeric_limits<double>::epsilon(); + } + + if (! (tmpRegion == e.m_pNode->m_nodeMBR)) + { + std::cerr << "Invalid parent information." << std::endl; + ret = false; + } + if (! (tmpRegion == e.m_parentMBR)) + { + std::cerr << "Error in parent." << std::endl; + ret = false; + } + + if (e.m_pNode->m_level != 0) + { + for (uint32_t cChild = 0; cChild < e.m_pNode->m_children; ++cChild) + { + NodePtr ptrN = readNode(e.m_pNode->m_pIdentifier[cChild]); + ValidateEntry tmpEntry(*(e.m_pNode->m_ptrMBR[cChild]), ptrN); + + std::map<uint32_t, uint32_t>::iterator itNodes = nodesInLevel.find(tmpEntry.m_pNode->m_level); + + if (itNodes == nodesInLevel.end()) + { + nodesInLevel.insert(std::pair<uint32_t, uint32_t>(tmpEntry.m_pNode->m_level, 1l)); + } + else + { + nodesInLevel[tmpEntry.m_pNode->m_level] = nodesInLevel[tmpEntry.m_pNode->m_level] + 1; + } + + st.push(tmpEntry); + } + } + } + + uint32_t nodes = 0; + for (uint32_t cLevel = 0; cLevel < m_stats.m_treeHeight; ++cLevel) + { + if (nodesInLevel[cLevel] != m_stats.m_nodesInLevel[cLevel]) + { + std::cerr << "Invalid nodesInLevel information." << std::endl; + ret = false; + } + + nodes += m_stats.m_nodesInLevel[cLevel]; + } + + if (nodes != m_stats.m_nodes) + { + std::cerr << "Invalid number of nodes information." << std::endl; + ret = false; + } + + return ret; +} + +void SpatialIndex::TPRTree::TPRTree::getStatistics(IStatistics** out) const +{ + *out = new Statistics(m_stats); +} + +void SpatialIndex::TPRTree::TPRTree::initNew(Tools::PropertySet& ps) +{ + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != TPRV_RSTAR)) + throw Tools::IllegalArgumentException("initNew: Property TreeVariant must be Tools::VT_LONG and of TPRTreeVariant type"); + + m_treeVariant = static_cast<TPRTreeVariant>(var.m_val.lVal); + } + + // fill factor + // it cannot be larger than 50%, since linear and quadratic split algorithms + // require assigning to both nodes the same number of entries. + var = ps.getProperty("FillFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property FillFactor must be Tools::VT_DOUBLE and in (0.0, 1.0) for RSTAR"); + + m_fillFactor = var.m_val.dblVal; + } + + // horizon + var = ps.getProperty("Horizon"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal == std::numeric_limits<double>::max()) + throw Tools::IllegalArgumentException("initNew: Property Horizon must be Tools::VT_DOUBLE and a positive constant"); + + m_horizon = var.m_val.dblVal; + } + + // index capacity + var = ps.getProperty("IndexCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property IndexCapacity must be Tools::VT_ULONG and >= 4"); + + m_indexCapacity = var.m_val.ulVal; + } + + // leaf capacity + var = ps.getProperty("LeafCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG || var.m_val.ulVal < 4) + throw Tools::IllegalArgumentException("initNew: Property LeafCapacity must be Tools::VT_ULONG and >= 4"); + + m_leafCapacity = var.m_val.ulVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initNew: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initNew: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // dimension + var = ps.getProperty("Dimension"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be Tools::VT_ULONG"); + if (var.m_val.ulVal <= 1) + throw Tools::IllegalArgumentException("initNew: Property Dimension must be greater than 1"); + + m_dimension = var.m_val.ulVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) + throw Tools::IllegalArgumentException("initNew: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) + throw Tools::IllegalArgumentException("initNew: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); + + m_stats.m_treeHeight = 1; + m_stats.m_nodesInLevel.push_back(0); + + Leaf root(this, -1); + m_rootID = writeNode(&root); + + storeHeader(); +} + +void SpatialIndex::TPRTree::TPRTree::initOld(Tools::PropertySet& ps) +{ + loadHeader(); + + // only some of the properties may be changed. + // the rest are just ignored. + + Tools::Variant var; + + // tree variant + var = ps.getProperty("TreeVariant"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_LONG || + (var.m_val.lVal != TPRV_RSTAR)) + throw Tools::IllegalArgumentException("initOld: Property TreeVariant must be Tools::VT_LONG and of TPRTreeVariant type"); + + m_treeVariant = static_cast<TPRTreeVariant>(var.m_val.lVal); + } + + // horizon + var = ps.getProperty("Horizon"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_DOUBLE || + var.m_val.dblVal <= 0.0 || + var.m_val.dblVal == std::numeric_limits<double>::max()) + throw Tools::IllegalArgumentException("initOld: Property Horizon must be Tools::VT_DOUBLE and a positive constant"); + + m_horizon = var.m_val.dblVal; + } + + // near minimum overlap factor + var = ps.getProperty("NearMinimumOverlapFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if ( + var.m_varType != Tools::VT_ULONG || + var.m_val.ulVal < 1 || + var.m_val.ulVal > m_indexCapacity || + var.m_val.ulVal > m_leafCapacity) + throw Tools::IllegalArgumentException("initOld: Property NearMinimumOverlapFactor must be Tools::VT_ULONG and less than both index and leaf capacities"); + + m_nearMinimumOverlapFactor = var.m_val.ulVal; + } + + // split distribution factor + var = ps.getProperty("SplitDistributionFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property SplitDistributionFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_splitDistributionFactor = var.m_val.dblVal; + } + + // reinsert factor + var = ps.getProperty("ReinsertFactor"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_DOUBLE || var.m_val.dblVal <= 0.0 || var.m_val.dblVal >= 1.0) + throw Tools::IllegalArgumentException("initOld: Property ReinsertFactor must be Tools::VT_DOUBLE and in (0.0, 1.0)"); + + m_reinsertFactor = var.m_val.dblVal; + } + + // tight MBRs + var = ps.getProperty("EnsureTightMBRs"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("initOld: Property EnsureTightMBRs must be Tools::VT_BOOL"); + + m_bTightMBRs = var.m_val.blVal; + } + + // index pool capacity + var = ps.getProperty("IndexPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property IndexPoolCapacity must be Tools::VT_ULONG"); + + m_indexPool.setCapacity(var.m_val.ulVal); + } + + // leaf pool capacity + var = ps.getProperty("LeafPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property LeafPoolCapacity must be Tools::VT_ULONG"); + + m_leafPool.setCapacity(var.m_val.ulVal); + } + + // region pool capacity + var = ps.getProperty("RegionPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property RegionPoolCapacity must be Tools::VT_ULONG"); + + m_regionPool.setCapacity(var.m_val.ulVal); + } + + // point pool capacity + var = ps.getProperty("PointPoolCapacity"); + if (var.m_varType != Tools::VT_EMPTY) + { + if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("initOld: Property PointPoolCapacity must be Tools::VT_ULONG"); + + m_pointPool.setCapacity(var.m_val.ulVal); + } + + m_infiniteRegion.makeInfinite(m_dimension); +} + +void SpatialIndex::TPRTree::TPRTree::storeHeader() +{ + const uint32_t headerSize = + sizeof(id_type) + // m_rootID + sizeof(TPRTreeVariant) + // m_treeVariant + sizeof(double) + // m_fillFactor + sizeof(uint32_t) + // m_indexCapacity + sizeof(uint32_t) + // m_leafCapacity + sizeof(uint32_t) + // m_nearMinimumOverlapFactor + sizeof(double) + // m_splitDistributionFactor + sizeof(double) + // m_reinsertFactor + sizeof(uint32_t) + // m_dimension + sizeof(char) + // m_bTightMBRs + sizeof(uint32_t) + // m_stats.m_nodes + sizeof(uint64_t) + // m_stats.m_data + sizeof(double) + // m_currentTime + sizeof(double) + // m_horizon + sizeof(uint32_t) + // m_stats.m_treeHeight + m_stats.m_treeHeight * sizeof(uint32_t);// m_stats.m_nodesInLevel + + byte* header = new byte[headerSize]; + byte* ptr = header; + + memcpy(ptr, &m_rootID, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(ptr, &m_treeVariant, sizeof(TPRTreeVariant)); + ptr += sizeof(TPRTreeVariant); + memcpy(ptr, &m_fillFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_indexCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_leafCapacity, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_nearMinimumOverlapFactor, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &m_splitDistributionFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_reinsertFactor, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_dimension, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c = (char) m_bTightMBRs; + memcpy(ptr, &c, sizeof(char)); + ptr += sizeof(char); + memcpy(ptr, &(m_stats.m_nodes), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(ptr, &(m_stats.m_data), sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(ptr, &m_currentTime, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &m_horizon, sizeof(double)); + ptr += sizeof(double); + memcpy(ptr, &(m_stats.m_treeHeight), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_treeHeight; ++cLevel) + { + memcpy(ptr, &(m_stats.m_nodesInLevel[cLevel]), sizeof(uint32_t)); + ptr += sizeof(uint32_t); + } + + m_pStorageManager->storeByteArray(m_headerID, headerSize, header); + + delete[] header; +} + +void SpatialIndex::TPRTree::TPRTree::loadHeader() +{ + uint32_t headerSize; + byte* header = 0; + m_pStorageManager->loadByteArray(m_headerID, headerSize, &header); + + byte* ptr = header; + + memcpy(&m_rootID, ptr, sizeof(id_type)); + ptr += sizeof(id_type); + memcpy(&m_treeVariant, ptr, sizeof(TPRTreeVariant)); + ptr += sizeof(TPRTreeVariant); + memcpy(&m_fillFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_indexCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_leafCapacity, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_nearMinimumOverlapFactor, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&m_splitDistributionFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_reinsertFactor, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_dimension, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + char c; + memcpy(&c, ptr, sizeof(char)); + m_bTightMBRs = (c != 0); + ptr += sizeof(char); + memcpy(&(m_stats.m_nodes), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + memcpy(&(m_stats.m_data), ptr, sizeof(uint64_t)); + ptr += sizeof(uint64_t); + memcpy(&m_currentTime, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&m_horizon, ptr, sizeof(double)); + ptr += sizeof(double); + memcpy(&(m_stats.m_treeHeight), ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + + for (uint32_t cLevel = 0; cLevel < m_stats.m_treeHeight; ++cLevel) + { + uint32_t cNodes; + memcpy(&cNodes, ptr, sizeof(uint32_t)); + ptr += sizeof(uint32_t); + m_stats.m_nodesInLevel.push_back(cNodes); + } + + delete[] header; +} + +void SpatialIndex::TPRTree::TPRTree::insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mr, id_type id) +{ + assert(mr.getDimension() == m_dimension); + assert(m_currentTime <= mr.m_startTime); + + std::stack<id_type> pathBuffer; + byte* overflowTable = 0; + + try + { + NodePtr root = readNode(m_rootID); + + overflowTable = new byte[root->m_level]; + bzero(overflowTable, root->m_level); + + NodePtr l = root->chooseSubtree(mr, 0, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + l->insertData(dataLength, pData, mr, id, pathBuffer, overflowTable); + + delete[] overflowTable; + ++(m_stats.m_data); + } + catch (...) + { + delete[] overflowTable; + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mr, id_type id, uint32_t level, byte* overflowTable) +{ + assert(mr.getDimension() == m_dimension); + + std::stack<id_type> pathBuffer; + NodePtr root = readNode(m_rootID); + NodePtr n = root->chooseSubtree(mr, level, pathBuffer); + + assert(n->m_level == level); + + if (n.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + n->insertData(dataLength, pData, mr, id, pathBuffer, overflowTable); +} + +bool SpatialIndex::TPRTree::TPRTree::deleteData_impl(const MovingRegion& mr, id_type id) +{ + assert(mr.m_dimension == m_dimension); + + std::stack<id_type> pathBuffer; + + NodePtr root = readNode(m_rootID); + NodePtr l = root->findLeaf(mr, id, pathBuffer); + if (l.get() == root.get()) + { + assert(root.unique()); + root.relinquish(); + } + + if (l.get() != 0) + { + Leaf* pL = static_cast<Leaf*>(l.get()); + pL->deleteData(id, pathBuffer); + --(m_stats.m_data); + return true; + } + + return false; +} + +id_type SpatialIndex::TPRTree::TPRTree::writeNode(Node* n) +{ + byte* buffer; + uint32_t dataLength; + n->storeToByteArray(&buffer, dataLength); + + id_type page; + if (n->m_identifier < 0) page = StorageManager::NewPage; + else page = n->m_identifier; + + try + { + m_pStorageManager->storeByteArray(page, dataLength, buffer); + delete[] buffer; + } + catch (InvalidPageException& e) + { + delete[] buffer; + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("writeNode: failed with Tools::InvalidPageException"); + } + + if (n->m_identifier < 0) + { + n->m_identifier = page; + ++(m_stats.m_nodes); + +#ifndef NDEBUG + try + { + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel.at(n->m_level) + 1; + } + catch(...) + { + throw Tools::IllegalStateException("writeNode: writing past the end of m_nodesInLevel."); + } +#else + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] + 1; +#endif + } + + ++(m_stats.m_writes); + + for (size_t cIndex = 0; cIndex < m_writeNodeCommands.size(); ++cIndex) + { + m_writeNodeCommands[cIndex]->execute(*n); + } + + return page; +} + +SpatialIndex::TPRTree::NodePtr SpatialIndex::TPRTree::TPRTree::readNode(id_type id) +{ + uint32_t dataLength; + byte* buffer; + + try + { + m_pStorageManager->loadByteArray(id, dataLength, &buffer); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("readNode: failed with Tools::InvalidPageException"); + } + + try + { + uint32_t nodeType; + memcpy(&nodeType, buffer, sizeof(uint32_t)); + + NodePtr n; + + if (nodeType == PersistentIndex) n = m_indexPool.acquire(); + else if (nodeType == PersistentLeaf) n = m_leafPool.acquire(); + else throw Tools::IllegalStateException("readNode: failed reading the correct node type information"); + + if (n.get() == 0) + { + if (nodeType == PersistentIndex) n = NodePtr(new Index(this, -1, 0), &m_indexPool); + else if (nodeType == PersistentLeaf) n = NodePtr(new Leaf(this, -1), &m_leafPool); + } + + //n->m_pTree = this; + n->m_identifier = id; + n->loadFromByteArray(buffer); + + ++(m_stats.m_reads); + + for (size_t cIndex = 0; cIndex < m_readNodeCommands.size(); ++cIndex) + { + m_readNodeCommands[cIndex]->execute(*n); + } + + delete[] buffer; + return n; + } + catch (...) + { + delete[] buffer; + throw; + } +} + +void SpatialIndex::TPRTree::TPRTree::deleteNode(Node* n) +{ + try + { + m_pStorageManager->deleteByteArray(n->m_identifier); + } + catch (InvalidPageException& e) + { + std::cerr << e.what() << std::endl; + //std::cerr << *this << std::endl; + throw Tools::IllegalStateException("deleteNode: failed with Tools::InvalidPageException"); + } + + --(m_stats.m_nodes); + m_stats.m_nodesInLevel[n->m_level] = m_stats.m_nodesInLevel[n->m_level] - 1; + + for (size_t cIndex = 0; cIndex < m_deleteNodeCommands.size(); ++cIndex) + { + m_deleteNodeCommands[cIndex]->execute(*n); + } +} + +void SpatialIndex::TPRTree::TPRTree::rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v) +{ + const MovingRegion* mr = dynamic_cast<const MovingRegion*>(&query); + if (mr == 0) throw Tools::IllegalArgumentException("rangeQuery: Shape has to be a moving region."); + if (mr->m_startTime < m_currentTime || mr->m_endTime >= m_currentTime + m_horizon) + throw Tools::IllegalArgumentException("rangeQuery: Query time interval does not intersect current horizon."); + +#ifdef HAVE_PTHREAD_H + Tools::SharedLock lock(&m_rwLock); +#else + if (m_rwLock == false) m_rwLock = true; + else throw Tools::ResourceLockedException("rangeQuery: cannot acquire a shared lock"); +#endif + + try + { + std::stack<NodePtr> st; + NodePtr root = readNode(m_rootID); + + if (root->m_children > 0 && mr->intersectsRegionInTime(root->m_nodeMBR)) st.push(root); + + while (! st.empty()) + { + NodePtr n = st.top(); st.pop(); + + if (n->m_level == 0) + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + bool b; + if (type == ContainmentQuery) b = mr->containsRegionInTime(*(n->m_ptrMBR[cChild])); + else b = mr->intersectsRegionInTime(*(n->m_ptrMBR[cChild])); + + if (b) + { + Data data = Data(n->m_pDataLength[cChild], n->m_pData[cChild], *(n->m_ptrMBR[cChild]), n->m_pIdentifier[cChild]); + v.visitData(data); + ++(m_stats.m_queryResults); + } + } + } + else + { + v.visitNode(*n); + + for (uint32_t cChild = 0; cChild < n->m_children; ++cChild) + { + if (mr->intersectsRegionInTime(*(n->m_ptrMBR[cChild]))) st.push(readNode(n->m_pIdentifier[cChild])); + } + } + } + +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + } + catch (...) + { +#ifndef HAVE_PTHREAD_H + m_rwLock = false; +#endif + throw; + } +} + +std::ostream& SpatialIndex::TPRTree::operator<<(std::ostream& os, const TPRTree& t) +{ + os << "Dimension: " << t.m_dimension << std::endl + << "Fill factor: " << t.m_fillFactor << std::endl + << "Horizon: " << t.m_horizon << std::endl + << "Index capacity: " << t.m_indexCapacity << std::endl + << "Leaf capacity: " << t.m_leafCapacity << std::endl + << "Tight MBRs: " << ((t.m_bTightMBRs) ? "enabled" : "disabled") << std::endl; + + if (t.m_treeVariant == TPRV_RSTAR) + { + os << "Near minimum overlap factor: " << t.m_nearMinimumOverlapFactor << std::endl + << "Reinsert factor: " << t.m_reinsertFactor << std::endl + << "Split distribution factor: " << t.m_splitDistributionFactor << std::endl; + } + + if (t.m_stats.getNumberOfNodesInLevel(0) > 0) + os << "Utilization: " << 100 * t.m_stats.getNumberOfData() / (t.m_stats.getNumberOfNodesInLevel(0) * t.m_leafCapacity) << "%" << std::endl + << t.m_stats; + + #ifndef NDEBUG + os << "Leaf pool hits: " << t.m_leafPool.m_hits << std::endl + << "Leaf pool misses: " << t.m_leafPool.m_misses << std::endl + << "Index pool hits: " << t.m_indexPool.m_hits << std::endl + << "Index pool misses: " << t.m_indexPool.m_misses << std::endl + << "Region pool hits: " << t.m_regionPool.m_hits << std::endl + << "Region pool misses: " << t.m_regionPool.m_misses << std::endl + << "Point pool hits: " << t.m_pointPool.m_hits << std::endl + << "Point pool misses: " << t.m_pointPool.m_misses << std::endl; + #endif + + return os; +} diff --git a/sci-libs/libspatialindex/svn/trunk/src/tprtree/TPRTree.h b/sci-libs/libspatialindex/svn/trunk/src/tprtree/TPRTree.h new file mode 100644 index 000000000..2c28727cd --- /dev/null +++ b/sci-libs/libspatialindex/svn/trunk/src/tprtree/TPRTree.h @@ -0,0 +1,199 @@ +// Spatial Index Library +// +// Copyright (C) 2002 Navel Ltd. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Email: +// mhadji@gmail.com + +#pragma once + +#include "Statistics.h" +#include "Node.h" +#include "PointerPoolNode.h" + +namespace SpatialIndex +{ + namespace TPRTree + { + class TPRTree : public ISpatialIndex + { + class NNEntry; + + public: + TPRTree(IStorageManager&, Tools::PropertySet&); + // String Value Description + // ---------------------------------------------- + // IndexIndentifier VT_LONG If specified an existing index will be openened from the supplied + // storage manager with the given index id. Behaviour is unspecified + // if the index id or the storage manager are incorrect. + // Dimension VT_ULONG Dimensionality of the data that will be inserted. + // IndexCapacity VT_ULONG The index node capacity. Default is 100. + // LeafCapactiy VT_ULONG The leaf node capacity. Default is 100. + // FillFactor VT_DOUBLE The fill factor. Default is 70% + // Horizon VT_DOUBLE Horizon. Default is 20.0. + // TreeVariant VT_LONG Can be one of Linear, Quadratic or Rstar. Default is Rstar + // NearMinimumOverlapFactor VT_ULONG Default is 32. + // SplitDistributionFactor VT_DOUBLE Default is 0.4 + // ReinsertFactor VT_DOUBLE Default is 0.3 + // EnsureTightMBRs VT_BOOL Default is true + // IndexPoolCapacity VT_LONG Default is 100 + // LeafPoolCapacity VT_LONG Default is 100 + // RegionPoolCapacity VT_LONG Default is 1000 + // PointPoolCapacity VT_LONG Default is 500 + + virtual ~TPRTree(); + + // + // ISpatialIndex interface + // + virtual void insertData(uint32_t len, const byte* pData, const IShape& shape, id_type shapeIdentifier); + virtual bool deleteData(const IShape& shape, id_type id); + virtual void containsWhatQuery(const IShape& query, IVisitor& v); + virtual void intersectsWithQuery(const IShape& query, IVisitor& v); + virtual void pointLocationQuery(const Point& query, IVisitor& v); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v, INearestNeighborComparator&); + virtual void nearestNeighborQuery(uint32_t k, const IShape& query, IVisitor& v); + virtual void selfJoinQuery(const IShape& s, IVisitor& v); + virtual void queryStrategy(IQueryStrategy& qs); + virtual void getIndexProperties(Tools::PropertySet& out) const; + virtual void addCommand(ICommand* pCommand, CommandType ct); + virtual bool isIndexValid(); + virtual void getStatistics(IStatistics** out) const; + + private: + void initNew(Tools::PropertySet&); + void initOld(Tools::PropertySet& ps); + void storeHeader(); + void loadHeader(); + + void insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id); + void insertData_impl(uint32_t dataLength, byte* pData, MovingRegion& mbr, id_type id, uint32_t level, byte* overflowTable); + bool deleteData_impl(const MovingRegion& mbr, id_type id); + + id_type writeNode(Node*); + NodePtr readNode(id_type id); + void deleteNode(Node*); + + void rangeQuery(RangeQueryType type, const IShape& query, IVisitor& v); + + IStorageManager* m_pStorageManager; + + id_type m_rootID, m_headerID; + + TPRTreeVariant m_treeVariant; + + double m_fillFactor; + + uint32_t m_indexCapacity; + + uint32_t m_leafCapacity; + + uint32_t m_nearMinimumOverlapFactor; + // The R*-Tree 'p' constant, for calculating nearly minimum overlap cost. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.1] + + double m_splitDistributionFactor; + // The R*-Tree 'm' constant, for calculating spliting distributions. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.2] + + double m_reinsertFactor; + // The R*-Tree 'p' constant, for removing entries at reinserts. + // [Beckmann, Kriegel, Schneider, Seeger 'The R*-tree: An efficient and Robust Access Method + // for Points and Rectangles', Section 4.3] + + uint32_t m_dimension; + + MovingRegion m_infiniteRegion; + + Statistics m_stats; + + bool m_bTightMBRs; + + double m_currentTime; + + double m_horizon; + + Tools::PointerPool<Point> m_pointPool; + Tools::PointerPool<MovingRegion> m_regionPool; + Tools::PointerPool<Node> m_indexPool; + Tools::PointerPool<Node> m_leafPool; + + std::vector<Tools::SmartPointer<ICommand> > m_writeNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_readNodeCommands; + std::vector<Tools::SmartPointer<ICommand> > m_deleteNodeCommands; + +#ifdef HAVE_PTHREAD_H + pthread_rwlock_t m_rwLock; +#else + bool m_rwLock; +#endif + + class NNEntry + { + public: + id_type m_id; + IEntry* m_pEntry; + double m_minDist; + + NNEntry(id_type id, IEntry* e, double f) : m_id(id), m_pEntry(e), m_minDist(f) {} + ~NNEntry() {} + + struct ascending : public std::binary_function<NNEntry*, NNEntry*, bool> + { + bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_minDist > __y->m_minDist; } + }; + }; // NNEntry + + class NNComparator : public INearestNeighborComparator + { + public: + double getMinimumDistance(const IShape& query, const IShape& entry) + { + return query.getMinimumDistance(entry); + } + + double getMinimumDistance(const IShape& query, const IData& data) + { + IShape* pS; + data.getShape(&pS); + double ret = query.getMinimumDistance(*pS); + delete pS; + return ret; + } + }; // NNComparator + + class ValidateEntry + { + public: + ValidateEntry(MovingRegion& r, NodePtr& pNode) : m_parentMBR(r), m_pNode(pNode) {} + + MovingRegion m_parentMBR; + NodePtr m_pNode; + }; // ValidateEntry + + friend class Node; + friend class Leaf; + friend class Index; + + friend std::ostream& operator<<(std::ostream& os, const TPRTree& t); + }; // TPRTree + + std::ostream& operator<<(std::ostream& os, const TPRTree& t); + } +} |