spatialite作为一个sqlite3数据库的extension,使得sqlite3具有地理空间数据的处理能力。
spatialite在linux上的编译,中文资料太少了。在此记录一下编译及使用过程。
编译依赖库!没错,spatialite依赖了很多很多库。列举如下(直接粘贴了我cmakelist的内容):
#libproj.a
find_library(Proj_LIBRARY NAMES libproj.a)
link_libraries(${Proj_LIBRARY})
MESSAGE(proj_lib:${Proj_LIBRARY})
#geos_c.a
find_library(geos_c_library NAMES libgeos_c.a)
link_libraries(${geos_c_library})
MESSAGE(geos_c_lib:${geos_c_library})
find_library(geos_library NAMES geos)
link_libraries(${geos_library})
MESSAGE(geos_lib:${geos_library})
#freexl.a
find_library(freexl_library NAMES libfreexl.a)
link_libraries(${freexl_library})
MESSAGE(freexl_lib:${freexl_library})
#xml2.a
find_library(xml2_library NAMES libxml2.a )
link_libraries(${xml2_library})
MESSAGE(xml2_lib:${xml2_library})
#libiconv
find_library(iconv_library NAMES libiconv.a )
link_libraries(${iconv_library})
MESSAGE(iconv_lib:${iconv_library})
#libz
find_library(z_library NAMES libz.a )
link_libraries(${z_library})
MESSAGE(z_library:${z_library})
#libzma
find_library(lzma_library NAMES liblzma.a )
link_libraries(${lzma_library})
MESSAGE(lzma_library:${lzma_library})
link_libraries( libm.a pthread dl libc.a)
proj,geos,freexl,xml2,iconv,z,lzma,m,pthred,dl,c
除了m,pthread,dl,c
是标准库,其他的都需要自行编译。
依赖库的编译,此处不做详细描述了。方法大同小异:
$./configure --prefix="安装目录!" --enable-static=yes CXXFLAGS=-fPIC CFLAGS=-fPIC
$sudo make
$sudo make install
spatialite的编译过程与上面步骤相同。编译完成后,会生成 libspatialite.so,libspatialite.a,mod_spatialite.so
这个mod开头的是个啥呢?官方原文如下:
What's new in mod_spatialite
You'll probably be already accustomed to load SpatiaLite as a dynamic extension; but any previous version before 4.2 made no real distinction between loadable modules and general-purpose shared libraries.
As we painfully learned by direct on-the-field experience, this apparently simpler configuration caused lot of troubles: instabilities, sudden crashes and so on. Making a clearer distinction between a general-purpose shared library and a pure loadable module seems to be the definitive solution.
Exactly here is the radical innovation introduce starting since version 4.2; now SpatiaLite is distributed in two alternative flavors:
- libspatialite (.so, .dll, .dylib and so on): a genuine classic shared library.
It will always depend on some external libsqlite3, and is uniquely intended to be used by stand-alone applications (such as e.g. spatialite or spatialite_gui).
You'll never be able to successfully load this libspatialite shared library as a dynamic extension via the SELECT load_extension mechanism, simply because it doesn't declare the required conventional interface.- mod_spatialite (.so, .dll, .dylib and so on): this is simply intended as pure loadable module lacking any explicit SQLite3 dependency.
You'll never be able to directly link this mod_spatialite shared library following the classic way, because it doesn't declare any external link symbol except that a single one: i.e. the conventional interface. The unique possible way to load and activate this module is by calling a SELECT load_extension SQL statement.
总而言之,言而总之:libspatialite可以用作项目的依赖库。mod_spatialite不可以!
mod_spatialite是sqlite3的extension,可以通过sqlite3_load_extesiong接口动态加载。如果你要使用这个方式去使用spatialite,那就用这个吧。
我使用的方式是忽略mod_spatialite,正常使用libspatialite.a。
接下啦,在项目中正常添加libspatialite.a就可以啦。在cmakelist中添加:
#sqlite3/spatialite
find_path(Spatialite_INCLUDE_DIR NAMES spatialite.h)
find_library(Spatialite_LIBRARY libspatialite.a)
include_directories(${Spatialite_INCLUDE_DIR})
link_libraries(${Spatialite_LIBRARY})
MESSAGE(spatialite_lib:${Spatialite_LIBRARY})
MESSAGE(spatialite_include:${Spatialite_INCLUDE_DIR})
#sqlite3secure.a 这是一个sqlite3的加密库!!!!!
find_library(Sqlite3Secure_LIBRARY NAMES libsqlite3secure.a)
link_libraries(${Sqlite3Secure_LIBRARY})
MESSAGE(sqlite3secure_lib:${Sqlite3Secure_LIBRARY})
官方提供了一些demo:http://www.gaia-gis.it/gaia-sins/splite-doxy-4.3.0/examples.html
需要注意的是,官方给的例子是使用sqlite3_load_extension来动态加载spatialite。
以下是我使用的方法
使用了sqlite3pp
#include <sqlite3.h>
#include <spatialite/gaiageo.h>
#include <spatialite.h>
...
...
gaiaVectorLayerPtr lyr;
LaneMarkingInfo* lmarking = nullptr;
auto handle = SqliteSingleton::getInstance();
stringstream ss;
ss << "SELECT marking_id, marking_type, marking_color,marking_material, marking_width ,CastToLinestring(geometry) FROM hd_lane_marking ";
ss << " WHERE ROWID IN (SELECT pkid FROM idx_hd_lane_marking_geometry WHERE xmin > " << rcBound.left;
ss << " and xmax < " << rcBound.right;
ss << " and ymin > " << rcBound.bottom;
ss << " and ymax <" << rcBound.top << ")";
sqlite3pp::query qry(*handle.get(),ss.str().c_str());
gaiaLinestringPtr geom;
for (auto i = qry.begin(); i != qry.end(); ++i) {
lmarking = new LaneMarkingInfo;
lmarking->nId = (*i).get<long long>(0);
lmarking->nShape = (*i).get<int32_t>(1);
lmarking->nColor = (*i).get<int32_t>(2);
lmarking->nMaterial = (*i).get<int32_t>(3);
lmarking->nWidth = (*i).get<int32_t>(4);
const unsigned char* pBuf = (const unsigned char*)(*i).get<const char*>(5);
int nBlobSize = (*i).column_bytes(5);
geom = gaiaFromSpatiaLiteBlobWkb(pBuf, nBlobSize)->FirstLinestring;
int nCount = geom->Points;
Point3D* pts = new Point3D[nCount];
for (int i =0; i < nCount; i++)
{
pts[i].x = geom->Coords[2 * i];
pts[i].y = geom->Coords[2 * i + 1];
pts[i].z = 0;
}
lmarking->pPts = pts;
lmarking->nCount = nCount;
listObj.push_back(lmarking);
gaiaFreeLinestring(geom);
}
return true;
说到底,编译使用的过程都很简单。困难与痛苦的地方在于查资料。