diff --git a/README.md b/README.md index dba141e..973873f 100644 --- a/README.md +++ b/README.md @@ -17,41 +17,44 @@ ## 命令行格式 ```sh -Converter.exe --format --input --output [OPTIONS] +Converter.exe --format [OPTIONS] ``` ## 示例命令 ```sh # from osgb dataset -Converter.exe --format osgb -input --output --yUpAxis true +Converter -f OSGB --yUpAxis # from single shp file -Converter.exe --format gdal --input --output --field height --layer +Converter -f GDAL --field height # from gdb file -Converter.exe --format gdal --input --output --field height --layer +Converter -f GDAL --field height --layer ``` ## 参数说明 -- `--format ` 输入数据格式。 - - `FORMAT` 可选:OSGB, GDAL - - `可选:OSGB` 为倾斜摄影格式数据, `GDAL` 为GDAL支持的面(Polygon)数据 - -- `--input ` 输入数据的目录,osgb数据截止到 `/Data` 目录的上一级,GDAL参考GDAL数据格式。 - -- `--output ` 输出目录。OSGB转换的3DTiles输出的数据文件位于 `/Data` 目录, GDAL转换的3DTiles输出的数据文件位于`/Tile`目录,`tileset.json`位于``根目录。 - -- `--field` 高度字段。指定GDAL数据集中的高度属性字段,此项为转换 GDAL 时的必须参数。 - -- `--offset` OSGB高度偏移字段。 -- `--thread` 处理线程数量(仅对OSGB生效) -- `--yUpAxis` 是否将gltf模型转为y轴朝上 - - `yUpAxis` 可选: true, false - 如果是用`Cesium for Unreal`加载数据,需要启用yUpAxis +``` +Options: + -?, -h, --help Displays help on commandline options. + + -f, --format OSGB or GDAL(required), OSGB 为倾斜摄影格式数据, GDAL 为GDAL支持的面(Polygon)数据 + + -l, --level OSGB max level, OSGB处理到的最大级别 + + -F, --field height field name(required for gdal), 指定GDAL数据集中的高度属性字段,此项为转换 GDAL 时的必须参数。 + + -L, --layer layer name(required when input isn't shapefile) + + -t, --thread thread number, 处理线程数量 + + -y, --yUpAxis y up axis, 是否将gltf模型转为y轴朝上(仅对OSGB生效),如果是用Cesium for Unreal,需要指定yUpAxis + + -H, --height height offset(default value 0), OSGB高度偏移字段 + + 输入数据的目录,OSGB数据截止到 `/Data` 目录的上一级,GDAL参考GDAL数据格式。 + 输出目录。OSGB转换的3DTiles输出的数据文件位于 /Data`目录, GDAL转换的3DTiles输出的数据文件位于/Tile目录,tileset.json位于根目录。 +``` # 数据要求及说明 diff --git a/include/Cesium3DTiles/BoundingVolumeBox.h b/include/Cesium3DTiles/BoundingVolumeBox.h index 72ee8c8..d29b298 100644 --- a/include/Cesium3DTiles/BoundingVolumeBox.h +++ b/include/Cesium3DTiles/BoundingVolumeBox.h @@ -17,71 +17,24 @@ namespace scially { struct BoundingVolumeBox{ static constexpr const char* TypeName = "box"; - BoundingVolumeBox() = default; - BoundingVolumeBox(BoundingVolumeRegion r) : region(r) {} - QJsonArray write() const; void read(const QJsonArray& object); - double centerX() const{ - return (region.east + region.west) / 2; - } - double centerY() const { - return (region.north + region.south) / 2; - } - double centerZ() const { - return (region.minHeight + region.maxHeight) / 2; - } - - double directionX0 () const { - return 0; - } - double directionX1 () const { - return 0; - } - double halfXLength () const { - return (region.east - region.west) / 2; - } - - double directionY0() const { - return 0; - } - - double directionY1() const { - return 0; - } - - double halfYLength () const { - return (region.north - region.south) / 2; - } - - double directionZ0 () const { - return 0; - } - - double directionZ1() const { - return 0; - } - - double halfZLength () const { - return (region.maxHeight - region.minHeight) / 2; - } - - void setMax(const osg::Vec3d& max); - void setMin(const osg::Vec3d& min); - void setMax(const osg::Vec3f& max); - void setMin(const osg::Vec3f& min); - - void mergeMax(const osg::Vec3d& max); - void mergeMin(const osg::Vec3d& min); - void mergeMax(const osg::Vec3f& max); - void mergeMin(const osg::Vec3f& min); - - BoundingVolumeBox merge(BoundingVolumeBox bounding) const; - - double geometricError() const; - osg::Vec3d getMax() const; - osg::Vec3d getMin() const; - - BoundingVolumeRegion region; + double geometricError() const noexcept; + + double centerX = 0; + double centerY = 0; + double centerZ = 0; + + double directionX0 = 0; + double directionX1 = 0; + double halfXLength = 0; + + double directionY0 = 0; + double directionY1 = 0; + double halfYLength = 0; + + double directionZ0 = 0; + double directionZ1 = 0; + double halfZLength = 0; }; } diff --git a/include/CommandLineParse.h b/include/CommandLineParse.h new file mode 100644 index 0000000..5cfac69 --- /dev/null +++ b/include/CommandLineParse.h @@ -0,0 +1,133 @@ +#pragma once + +#include +#include +#include + +namespace scially { + class CommandLineParseException : public QException { + public: + explicit CommandLineParseException(const QString& err) : err_(err) { + } + void raise() const override { throw* this; } + CommandLineParseException* clone() const override { return new CommandLineParseException(*this); } + QString error() const noexcept { return err_; } + private: + QString err_; + }; + + class CommandLineParse + { + public: + CommandLineParse() { + parser_.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); + parser_.setApplicationDescription("Convert OSGB, GDAL to Cesium 3DTiles"); + parser_.addHelpOption(); + parser_.addVersionOption(); + } + void parse() { + parser_.addOptions({ + { + QStringList() << "f" << "format", + "OSGB or GDAL(required)", "format" + }, + { + QStringList() << "l" << "level", + "osgb max level", "level", "-1" + }, + { + QStringList() << "F" << "field", + "height field name(required for gdal)", "field" + }, + { + QStringList() << "L" << "layer", + "layer name(required when input isn't shapefile)", "layer" + }, + { + QStringList() << "t" << "thread", + "thread number", "thread", "4" + }, + { + QStringList() << "y" << "yUpAxis", + "y up axis", "yUpAxis" + }, + { + QStringList() << "H" << "height", + "height offset(default value 0)", "height", "0" + } + }); + + parser_.process(*qApp); + thread_ = parser_.value("thread").toInt(); + + if (!parser_.isSet("format")) + throw CommandLineParseException("commandline format is requested"); + format_ = parser_.value("format").toUpper(); + + if (format_ == "GDAL") { + parseGDAL(); + } + else if (format_ == "OSGB") { + parseOSGB(); + } + else + throw CommandLineParseException("format must be GDAL or OSGB"); + parseIO(); + } + void showHelp(int exitCode = -1) { + parser_.showHelp(); + } + QString format() const noexcept { return format_; } + QString input() const noexcept { return input_; } + QString output() const noexcept { return output_; } + int level() const noexcept { return level_; } + int thread() const noexcept { return thread_; } + bool yUpAxis() const noexcept { return yUpAxis_; } + double height() const noexcept { return height_; } + QString field() const noexcept { return field_; } + QString layer() const noexcept { return layer_; } + + private: + void parseOSGB() { + level_ = parser_.value("level") == "-1" ? + std::numeric_limits::max() : parser_.value("level").toInt(); + height_ = parser_.value("height") == "0" ? 0 : parser_.value("height").toDouble(); + yUpAxis_ = parser_.isSet("yUpAxis"); + } + void parseGDAL() { + if (!parser_.isSet("field")) + throw CommandLineParseException("commandline field is requested"); + field_ = parser_.value("field"); + } + + void parseIO() { + const QStringList args = parser_.positionalArguments(); + if (args.size() != 2) { + throw CommandLineParseException("input and out must be set"); + } + input_ = args[0]; + QFileInfo inputFile(input_); + if (!inputFile.exists()) { + throw CommandLineParseException("input file " + input_ + "not exist"); + } + if (inputFile.fileName().indexOf(".shp") < 0 && !layer_.isEmpty()) { + throw CommandLineParseException("layer name must be set"); + } + if (inputFile.fileName().indexOf(".shp") >= 0 && layer_.isEmpty()) { + layer_ = inputFile.baseName(); + } + output_ = args[1]; + } + + QString format_; + QString input_; + QString output_; + int level_; + int thread_; + bool yUpAxis_; + double height_; + QString field_; + QString layer_; + QCommandLineParser parser_; + }; +} \ No newline at end of file diff --git a/include/GDALWrapper.h b/include/GDALWrapper.h index a5c917c..8682cd4 100644 --- a/include/GDALWrapper.h +++ b/include/GDALWrapper.h @@ -12,11 +12,7 @@ namespace scially { class GDALDriverWrapper { public: GDALDriverWrapper() { -#ifdef _WIN32 - CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); -#else CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); -#endif std::string basePath = qApp->applicationDirPath().toStdString(); gdalData = basePath + "/gdal_data"; projData = basePath + "/proj_data"; diff --git a/include/OSGBConvert.h b/include/OSGBConvert.h index a5abb82..4d7a5f3 100644 --- a/include/OSGBConvert.h +++ b/include/OSGBConvert.h @@ -1,45 +1,44 @@ #pragma once -#include -#include - +#include #include #include -#include -#include -#include -#include +#include +#include namespace scially { class OSGBConvert { public: OSGBConvert() {} OSGBConvert(const QString& name, const QString& path) : - nodeName(name), nodePath(path) {} - OSGBConvert(const QString& absoluteLocation) { - QDir location(absoluteLocation); - nodeName = location.dirName(); - location.cdUp(); - nodePath = location.absolutePath(); + nodeName_(name), nodePath_(path) { + nodeLocation_ = QDir::cleanPath(path + "/" + name + ".osgb"); } - //double geometricError = 0; - BoundingVolumeRegion region; + OSGBConvert(const QString& absoluteLocation) : nodeLocation_(absoluteLocation){ + QFileInfo location(nodeLocation_); + nodeName_ = location.baseName(); + nodePath_ = location.path(); + } bool writeB3DM(const QByteArray& buffer, const QString& outLocation); - QByteArray toB3DM(); - - bool yUpAxis = false; + bool toB3DM(QByteArray& buffer); + void setYUpAxis(bool yUpAxis) noexcept { yUpAxis_ = yUpAxis; } + OSGBRegion region() const noexcept { return region_; } + bool yUpAxis() const noexcept { return yUpAxis_; } + QString nodeName() const noexcept { return nodeName_; } + QString nodePath() const noexcept { return nodePath_; } private: tinygltf::Material makeColorMaterialFromRGB(double r, double g, double b); - QByteArray convertGLB(); - QString absoluteLocation() const; - - QString nodeName; - QString nodePath; + bool convertGLB(QByteArray& buffer); + OSGBRegion region_; + bool yUpAxis_ = false; + QString nodeName_; + QString nodePath_; + QString nodeLocation_; }; } diff --git a/include/OSGBConvertJob.h b/include/OSGBConvertJob.h index 70f74e2..a6524b7 100644 --- a/include/OSGBConvertJob.h +++ b/include/OSGBConvertJob.h @@ -1,15 +1,12 @@ #pragma once #include +#include -#include #include -#include #include #include -#include -#include -#include +#include namespace scially { class OSGBConvertTask; @@ -17,68 +14,61 @@ namespace scially { class OSGBConvertJob: public QObject{ Q_OBJECT public: - OSGBConvertJob(const QString& input, const QString &output) - :input(input), output(output), threadPool(new QThreadPool) {} + OSGBConvertJob(const QString& input, const QString &output, QObject* parent = nullptr) + :input_(input), output_(output), QObject(parent) { + threadPool_ = new QThreadPool(this); + } - void setMaxThread(int thread){ - maxThread = thread; - threadPool->setMaxThreadCount(maxThread); + void setThread(int thread){ + threadPool_->setMaxThreadCount(thread); } void run(); - virtual ~OSGBConvertJob() { - if(threadPool != nullptr) - delete threadPool; - } + void setHeight(double h) {height_ = h; } + void setMaxLevel(int level){ maxLevel_ = level; } + void setYUpAxis(bool yUpAxis){yUpAxis_ = yUpAxis; } - void setHeight(double h) {height = h;} - void setMaxLevel(int level){ maxLevel = level; } - void setYUpAxis(bool y){yUpAxis = y;} private: - QString input; - QString output; - double height = 0; - bool yUpAxis = false; - QThreadPool *threadPool; - int maxThread = 4; - int maxLevel = std::numeric_limits::max(); - QVector> tasks; + QString input_; + QString output_; + double height_ = 0; + bool yUpAxis_ = false; + QThreadPool * threadPool_; + int maxLevel_ = std::numeric_limits::max(); + QVector tasks_; }; class OSGBConvertTask: public QObject, public QRunnable{ Q_OBJECT public: - OSGBConvertTask(const QString& input, const QString& output, int maxLevel = std::numeric_limits::max()) - :osgbLevel(input), output(output), maxLevel(maxLevel){ + OSGBConvertTask(const QString& input, const QString& output, + int maxLevel = OSGLevel::MAXLEVEL, QObject* parent = nullptr) + :osgbLevel_(input), output_(output), maxLevel_(maxLevel), QObject(parent){ setAutoDelete(false); - }; virtual void run() override { - qInfo() << "Start process tile: " << osgbLevel.nodeName; - try{ - isSucceed = osgbLevel.convertTiles(tile, output, maxLevel); - }catch(...){ - qCritical() << "Unkown error"; - } + qInfo() << "start process tile:" << osgbLevel_.nodeName(); - if(isSucceed){ - qInfo() << "Finish process tile: " << osgbLevel.nodeName; - }else{ - qInfo() << "Not finish process tile: " << osgbLevel.nodeName; - } - - } - void setYUpAxis(bool y) { - osgbLevel.setYUpAxis(y); + success_ = osgbLevel_.convertTiles(tile_, output_, maxLevel_); + if (success_) + qInfo() << "finish process tile:" << osgbLevel_.nodeName(); + else + qCritical() << "error process tile" << osgbLevel_.nodeName(); } + + void setYUpAxis(bool y) noexcept { osgbLevel_.setYUpAxis(y); } - OSGBLevel osgbLevel; - bool isSucceed; - BaseTile tile; + OSGBRegion region() const noexcept { return osgbLevel_.region(); } + bool isSuccess() const { return success_; } + BaseTile baseTile() const { return tile_; } + QString tileName() const { return osgbLevel_.getTileName(); } private: - QString output; - int maxLevel; + OSGLevel osgbLevel_; + bool success_ = false; + BaseTile tile_; + QString output_; + int maxLevel_; }; -} +} \ No newline at end of file diff --git a/include/OSGBLevel.h b/include/OSGBLevel.h index 8ac3a6f..b5c19e7 100644 --- a/include/OSGBLevel.h +++ b/include/OSGBLevel.h @@ -2,56 +2,60 @@ #include #include +#include #include #include -#include -#include -#include -#include +#include #include namespace scially { - class OSGBLevel { + class OSGLevel { public: static constexpr const char* OSGBEXTENSION = ".osgb"; static constexpr const char* B3DMEXTENSION = ".b3dm"; + static constexpr int MAXLEVEL = 28; - using OSGBLevelPtr = QSharedPointer; - - OSGBLevel() = delete; - OSGBLevel(const QString& absoluteLocation) { - QDir location(absoluteLocation); - QString dirName = location.dirName(); - nodeName = dirName.left(dirName.lastIndexOf(".")); - location.cdUp(); - nodePath = location.absolutePath(); + OSGLevel(const QString& absoluteLocation): nodeLocation_(absoluteLocation){ + QFileInfo osgFile(absoluteLocation); + nodeName_ = osgFile.baseName(); + nodePath_ = osgFile.path(); } - double geometricError; - BoundingVolumeBox region; - QString nodeName; - QString nodePath; - QVector subNodes; - osg::Vec3d bBoxMax; - osg::Vec3d bBoxMin; - - QString absoluteLocation() const; - /// /// get Tile_+154_+018_L22_0000320.osgb _L level /// int getLevelNumber() const; QString getTileName() const; - bool getAllOSGBLevels(int maxLevel); + bool convertTiles(BaseTile &tile, const QString& output, int maxLevel = std::numeric_limits::max()); bool convertTiles(RootTile &root, const QString& output); - void updateGeometryError(RootTile &root); - void setYUpAxis(bool y) { yUpAxis = y; } + + OSGBRegion region() const { return region_; } + double geometricError() const { return geometricError_; } + QString nodeName() const { return nodeName_; } + QString nodePath() const { return nodePath_; } + QVector subNodes() const { return subNodes_; } + osg::Vec3d bBoxMax() const { return bBoxMax_; } + osg::Vec3d bBoxMin() const { return bBoxMin_; } + bool yUpAxis() const { return yUpAxis_; } + void setYUpAxis(bool y) { yUpAxis_ = y; } + + protected: + void createDir(const QString& output) const; + bool getAllOSGBLevels(int maxLevel); + void updateGeometryError(RootTile& root); private: - void createDir(const QString& output) const; - bool yUpAxis = false; + double geometricError_; + OSGBRegion region_; + QString nodeName_; + QString nodePath_; + QString nodeLocation_; + QVector subNodes_; + osg::Vec3d bBoxMax_; + osg::Vec3d bBoxMin_; + bool yUpAxis_ = false; }; } diff --git a/include/OSGBPageLodVisitor.h b/include/OSGBPageLodVisitor.h index e331bae..381ec00 100644 --- a/include/OSGBPageLodVisitor.h +++ b/include/OSGBPageLodVisitor.h @@ -32,7 +32,7 @@ namespace scially { QString path; QVector geometryArray; QSet textureArray; - QMap textureMap; // 记录 mesh 和 texture 的关系,暂时认为一个模型最多只有一个texture + QMap textureMap; QVector subNodeNames; }; } diff --git a/include/OSGBRegion.h b/include/OSGBRegion.h new file mode 100644 index 0000000..76f78e2 --- /dev/null +++ b/include/OSGBRegion.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include +#include + +#include + +namespace scially { + struct OSGBRegion { + osg::Vec3d getMax() const noexcept; + osg::Vec3d getMin() const noexcept; + + void setMax(const osg::Vec3d& max) noexcept; + void setMin(const osg::Vec3d& min) noexcept; + void setMax(const osg::Vec3f& max) noexcept; + void setMin(const osg::Vec3f& min) noexcept; + + void mergeMax(const osg::Vec3d& max) noexcept; + void mergeMin(const osg::Vec3d& min) noexcept; + void mergeMax(const osg::Vec3f& max) noexcept; + void mergeMin(const osg::Vec3f& min) noexcept; + + double geometricError() const noexcept { + double maxErr = std::max({ north - south, maxHeight - minHeight, east - west }); + return maxErr / 20.0; + } + + OSGBRegion merge(const OSGBRegion& bounding) const noexcept; + BoundingVolumeBox toBoundingVolumeBox() const noexcept; + + double west = std::numeric_limits::max(); + double south = std::numeric_limits::max(); + double east = std::numeric_limits::min(); + double north = std::numeric_limits::min(); + double minHeight = std::numeric_limits::max(); + double maxHeight = std::numeric_limits::min(); + }; +} diff --git a/include/TilesConvertException.h b/include/TilesConvertException.h index ed77ea5..3912375 100644 --- a/include/TilesConvertException.h +++ b/include/TilesConvertException.h @@ -14,4 +14,6 @@ namespace scially { private: QString err; }; + + } diff --git a/include/Utils.h b/include/Utils.h index 0d5553e..12f4988 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -1,15 +1,8 @@ #pragma once -#include -#include -#include -#include -#include - #include namespace scially { - /************************************* MATH Utils *****************************************************/ constexpr double METERIC = 0.01; @@ -44,15 +37,4 @@ namespace scially { inline float lonToMeter(float diff, float lat) { return osg::DegreesToRadians(diff) / 0.000000156785 * std::cos(osg::DegreesToRadians(lat)); } - - - /************************************* Json Utils *****************************************************/ - template - QJsonArray arrayToQJsonArray(Iter begin, Iter end) { - QJsonArray arr; - for (auto iter = begin; iter != end; iter++) { - arr.append(*iter); - } - return arr; - } } \ No newline at end of file diff --git a/include/tiny_gltf/tiny_gltf.h b/include/tiny_gltf/tiny_gltf.h index b3bd74d..ab9934b 100644 --- a/include/tiny_gltf/tiny_gltf.h +++ b/include/tiny_gltf/tiny_gltf.h @@ -2615,7 +2615,7 @@ namespace tinygltf { } json v; - + #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(TINYGLTF_NOEXCEPTION) try { diff --git a/src/Cesium3DTiles/Batched3DModel.cpp b/src/Cesium3DTiles/Batched3DModel.cpp index 4aaa66a..6698a60 100644 --- a/src/Cesium3DTiles/Batched3DModel.cpp +++ b/src/Cesium3DTiles/Batched3DModel.cpp @@ -23,11 +23,16 @@ namespace scially { // batch json and batch binary { QJsonObject batchJson; - batchJson["batchId"] = arrayToQJsonArray(batchID.begin(), batchID.end()); - batchJson["name"] = arrayToQJsonArray(names.begin(), names.end()); + QJsonArray batchIDArray, namesArray; + std::copy(batchID.begin(), batchID.end(), std::back_inserter(batchIDArray)); + std::copy(names.begin(), names.end(), std::back_inserter(namesArray)); + batchJson["batchId"] = batchIDArray; + batchJson["name"] = namesArray; if (withHeight) { - batchJson["height"] = arrayToQJsonArray(heights.begin(), heights.end()); + QJsonArray heightArray; + std::copy(heights.begin(), heights.end(), std::back_inserter(heightArray)); + batchJson["height"] = heightArray; } batch = QJsonDocument(batchJson).toJson(QJsonDocument::Compact); diff --git a/src/Cesium3DTiles/BoundingVolumeBox.cpp b/src/Cesium3DTiles/BoundingVolumeBox.cpp index e300a54..a5234e9 100644 --- a/src/Cesium3DTiles/BoundingVolumeBox.cpp +++ b/src/Cesium3DTiles/BoundingVolumeBox.cpp @@ -3,67 +3,30 @@ namespace scially { QJsonArray BoundingVolumeBox::write() const{ QJsonArray array; - array.append(centerX()); array.append(centerY()); array.append(centerZ()); - array.append(halfXLength()); array.append(directionX0()); array.append(directionX1()); - array.append(directionY0()); array.append(halfYLength()); array.append(directionY1()); - array.append(directionZ0()); array.append(directionZ1()); array.append(halfZLength()); + array.append(centerX); array.append(centerY); array.append(centerZ); + array.append(halfXLength); array.append(directionX0); array.append(directionX1); + array.append(directionY0); array.append(halfYLength); array.append(directionY1); + array.append(directionZ0); array.append(directionZ1); array.append(halfZLength); return array; } void BoundingVolumeBox::read(const QJsonArray& object) { - double centerX = object[0].toDouble(), centerY = object[1].toDouble(), centerZ = object[2].toDouble(); - double directionX0 = object[4].toDouble(), directionX1 = object[5].toDouble(), halfXLength = object[3].toDouble(); - double directionY0 = object[6].toDouble(), directionY1 = object[8].toDouble(), halfYLength = object[7].toDouble(); - double directionZ0 = object[9].toDouble(), directionZ1 = object[10].toDouble(), halfZLength = object[11].toDouble(); - - region.east = centerX + halfXLength; - region.west = centerX - halfXLength; - region.north = centerY + halfYLength; - region.south = centerY - halfYLength; - region.maxHeight = centerZ + halfZLength; - region.minHeight = centerZ - halfZLength; - } - - void BoundingVolumeBox::setMax(const osg::Vec3d& max){ - region.setMax(max); - } - void BoundingVolumeBox::setMin(const osg::Vec3d& min){ - region.setMax(min); - } - void BoundingVolumeBox::setMax(const osg::Vec3f& max){ - region.setMax(max); - } - void BoundingVolumeBox::setMin(const osg::Vec3f& min){ - region.setMin(min); - } - void BoundingVolumeBox::mergeMax(const osg::Vec3d& max) { - region.mergeMax(max); + centerX = object[0].toDouble(), centerY = object[1].toDouble(), centerZ = object[2].toDouble(); + directionX0 = object[4].toDouble(), directionX1 = object[5].toDouble(), halfXLength = object[3].toDouble(); + directionY0 = object[6].toDouble(), directionY1 = object[8].toDouble(), halfYLength = object[7].toDouble(); + directionZ0 = object[9].toDouble(), directionZ1 = object[10].toDouble(), halfZLength = object[11].toDouble(); } - void BoundingVolumeBox::mergeMin(const osg::Vec3d & min) { - region.mergeMin(min); - } + + double BoundingVolumeBox::geometricError() const noexcept { + double east = centerX + halfXLength; + double west = centerX - halfXLength; + double north = centerY + halfYLength; + double south = centerY - halfYLength; + double maxHeight = centerZ + halfZLength; + double minHeight = centerZ - halfZLength; - void BoundingVolumeBox::mergeMax(const osg::Vec3f& max) { - region.mergeMax(max); + double maxErr = std::max({ north - south, maxHeight - minHeight, east - west }); + return maxErr / 20.0; } - - void BoundingVolumeBox::mergeMin(const osg::Vec3f& min) { - region.mergeMin(min); - } - - osg::Vec3d BoundingVolumeBox::getMax() const { - return region.getMax(); - } - osg::Vec3d BoundingVolumeBox::getMin() const { - return region.getMax(); - } - double BoundingVolumeBox::geometricError() const { - return region.geometricError(); - } - - BoundingVolumeBox BoundingVolumeBox::merge(BoundingVolumeBox bounding) const { - BoundingVolumeBox box(region.merge(bounding.region)); - return box; - } } diff --git a/src/Conveter.cpp b/src/Conveter.cpp index eb5f9b2..e2412ea 100644 --- a/src/Conveter.cpp +++ b/src/Conveter.cpp @@ -1,92 +1,40 @@ #include #include #include +#include #include -#include #include int main(int argc, char** argv){ QCoreApplication app(argc, argv); scially::GDALDriverWrapper init; - QCoreApplication::setApplicationName("Cesium3DTilesConverter"); - QCoreApplication::setApplicationVersion("2.0"); - QTime beginTime = QTime::currentTime(); - - QCommandLineParser parser; - parser.setApplicationDescription("Convert OSGB, GDAL to Cesium 3DTiles"); - parser.addHelpOption(); - parser.addVersionOption(); - const QCommandLineOption inputOption("input", "input path", "input"); - parser.addOption(inputOption); - const QCommandLineOption outputOption("output", "output path", "output"); - parser.addOption(outputOption); - const QCommandLineOption formatOption("format", "", "format"); - parser.addOption(formatOption); - const QCommandLineOption maxLvlOption("level", "max level", "level", "-1"); - parser.addOption(maxLvlOption); - const QCommandLineOption heightOption("offset", "height offset", "offset", "0"); - parser.addOption(heightOption); - const QCommandLineOption fieldOption("field", "height field name", "filed"); - parser.addOption(fieldOption); - const QCommandLineOption layerOption("layer", "layer name", "layer"); - parser.addOption(layerOption); - const QCommandLineOption threadOption("thread", "thread count", "thread", "4"); - parser.addOption(threadOption); - const QCommandLineOption yUpAxis("yUpAxis", "y up axis", "yUpAxis"); - parser.addOption(yUpAxis); - - parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); - parser.process(app); - - if(!parser.isSet(formatOption)){ - qCritical() << "Commandline format is requested"; - return 1; - } - if(!parser.isSet(inputOption)){ - qCritical() << "Commandline input is requested"; - return 1; + scially::CommandLineParse cmd; + try { + cmd.parse(); } - if(!parser.isSet(outputOption)){ - qCritical() << "Commandline output is requested"; - return 1; + catch (scially::CommandLineParseException& e) { + qCritical() << e.error(); + cmd.showHelp(); } - const int thread = parser.value(threadOption).toInt(); - const QString input = parser.value(inputOption); - const QString output= parser.value(outputOption); - const QString format = parser.value(formatOption).toUpper(); - if(format == "OSGB"){ - const int maxLevel = parser.value(maxLvlOption) == "-1" ? std::numeric_limits::max(): parser.value(maxLvlOption).toInt(); - const double height = parser.value(heightOption) == "0" ? 0 : parser.value(heightOption).toDouble(); - scially::OSGBConvertJob osgbConvert(input, output); - if(parser.isSet(yUpAxis)) - osgbConvert.setYUpAxis(true); - - osgbConvert.setMaxLevel(thread); - osgbConvert.setHeight(height); - osgbConvert.setMaxLevel(maxLevel); + + QTime beginTime = QTime::currentTime(); + if (cmd.format() == "OSGB") { + scially::OSGBConvertJob osgbConvert(cmd.input(), cmd.output()); + osgbConvert.setYUpAxis(cmd.yUpAxis()); + osgbConvert.setMaxLevel(cmd.thread()); + osgbConvert.setHeight(cmd.height()); + osgbConvert.setMaxLevel(cmd.level()); osgbConvert.run(); } - else if (format == "GDAL"){ - if(!parser.isSet(fieldOption)){ - qCritical() << "Commandline field is requested"; - return 1; - } - if (!parser.isSet(layerOption)) { - qCritical() << "Commandline layer is requested"; - return 1; - } - const QString fieldName = parser.value(fieldOption); - const QString layerName = parser.value(layerOption); - - scially::ShpConvertJob shpConvert(input, layerName, output, fieldName); + + if (cmd.format() == "GDAL") { + scially::ShpConvertJob shpConvert(cmd.input(), cmd.layer(), + cmd.output(), cmd.field()); shpConvert.run(); } - else{ - qCritical() << "Only support OSGB and GDAL format"; - return 1; - } - qInfo() << "Finish convert in " << beginTime.secsTo( QTime::currentTime()) << "s"; + qInfo() << "finish convert in " << beginTime.secsTo(QTime::currentTime()) << "s"; + return 0; } diff --git a/src/OSGBConvert.cpp b/src/OSGBConvert.cpp index 130cd95..a6a1e18 100644 --- a/src/OSGBConvert.cpp +++ b/src/OSGBConvert.cpp @@ -9,53 +9,35 @@ #include #include + +#include #include #include #include #include -#include -#include - -#include -#include +#include namespace scially { - - QString OSGBConvert::absoluteLocation() const { - return QDir(nodePath).filePath(nodeName); - } - bool OSGBConvert::writeB3DM(const QByteArray &buffer, const QString& outLocation) { - - if (buffer.isEmpty()) { - qWarning() << "B3DM buffer is empty...\n"; - return false; - } - - // - QFile b3dmFile(outLocation + "/" + nodeName.replace(".osgb", ".b3dm")); + QFile b3dmFile(outLocation + "/" + nodeName_ + ".b3dm"); if (!b3dmFile.open(QIODevice::ReadWrite)) { - qWarning() << "Can't open file [" << b3dmFile.fileName() << "]\n"; + qWarning() << "can't write file" << b3dmFile.fileName(); return false; } int writeBytes = b3dmFile.write(buffer); if (writeBytes <= 0) { - qWarning() << "Can't write file [" << b3dmFile.fileName() << "]\n"; + qWarning() << "can't write file" << b3dmFile.fileName(); return false; } return true; } - QByteArray OSGBConvert::toB3DM() { - QByteArray b3dmBuffer; - QDataStream b3dmStream(&b3dmBuffer, QIODevice::WriteOnly); - b3dmStream.setByteOrder(QDataStream::LittleEndian); - - QByteArray glbBuffer = convertGLB(); - - if (glbBuffer.isEmpty()) - return QByteArray(); + bool OSGBConvert::toB3DM(QByteArray& buffer) { + QByteArray glbBuffer; + if (!convertGLB(glbBuffer)) { + return false; + } Batched3DModel b3dm; b3dm.glbBuffer = glbBuffer; @@ -63,24 +45,22 @@ namespace scially { b3dm.batchID = { 0 }; b3dm.names = {"mesh_0"}; - return b3dm.write(); + buffer = b3dm.write(); + return true; } - QByteArray OSGBConvert::convertGLB() { - QByteArray glbBuffer; - - std::vector rootOSGBLocation = { absoluteLocation().toStdString() }; - osg::ref_ptr root = osgDB::readNodeFiles(rootOSGBLocation); + bool OSGBConvert::convertGLB(QByteArray& glbBuffer) { + osg::ref_ptr root = osgDB::readNodeFile(nodeLocation_.toStdString()); if (!root.valid()) { - qWarning() << "Read OSGB File [" << absoluteLocation() << "] Fail...\n"; - return QByteArray(); + qWarning() << "fail read osgb file" << nodeLocation_; + return false; } - OSGBPageLodVisitor lodVisitor(nodePath); + OSGBPageLodVisitor lodVisitor(nodePath_); root->accept(lodVisitor); if (lodVisitor.geometryArray.empty()) { - qWarning() << "Read OSGB File [" << absoluteLocation() << "] geometries is Empty...\n"; - return QByteArray(); + qWarning() << "empty geometry in osgb file" << nodeLocation_; + return false; } osgUtil::SmoothingVisitor sv; @@ -129,12 +109,13 @@ namespace scially { } } } + // empty geometry or empty vertex-array if (model.meshes[0].primitives.empty()) - return QByteArray(); + return false; - region.setMax(osgState.pointMax); - region.setMin(osgState.pointMin); + region_.setMax(osgState.pointMax); + region_.setMin(osgState.pointMin); // image { @@ -200,7 +181,7 @@ namespace scially { { tinygltf::Node node; node.mesh = 0; - if(yUpAxis){ + if(yUpAxis_){ // z-UpAxis to y-UpAxis node.matrix = {1,0,0,0, 0,0,-1,0, @@ -260,10 +241,8 @@ namespace scially { model.asset.generator = "Cesium3DTilesConveter"; glbBuffer = QByteArray::fromStdString(gltf.Serialize(&model)); - return glbBuffer; + return true; } - - } tinygltf::Material OSGBConvert::makeColorMaterialFromRGB(double r, double g, double b) { diff --git a/src/OSGBConvertJob.cpp b/src/OSGBConvertJob.cpp index 0f90a3a..fc4d0ae 100644 --- a/src/OSGBConvertJob.cpp +++ b/src/OSGBConvertJob.cpp @@ -3,71 +3,60 @@ #include #include -#include -#include namespace scially { void OSGBConvertJob::run() { - // 解析XML中的坐标 ModelMetadata metadata; double lon, lat; - metadata.parse(input + "/metadata.xml"); + metadata.parse(input_ + "/metadata.xml"); metadata.getCoordinate(lon, lat); - // 遍历Data - QDir dataDir(input + "/Data"); + QDir dataDir(input_ + "/Data"); if(!dataDir.exists()){ - qCritical() << "Can't find Data dir in " << input; + qCritical() << "can't find Data in:" << input_; return; } QFileInfoList tileDirs = dataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot , QDir::Name); for(auto iter = tileDirs.constBegin(); iter != tileDirs.constEnd(); iter++){ - QString tileLocation = iter->absoluteFilePath() + "/" + iter->fileName() + OSGBLevel::OSGBEXTENSION; - auto task = QSharedPointer::create(tileLocation, output, maxLevel); - task->setYUpAxis(yUpAxis); - tasks.append(task); - threadPool->start(task.get()); + QString tileLocation = iter->absoluteFilePath() + "/" + iter->fileName() + OSGLevel::OSGBEXTENSION; + auto task = new OSGBConvertTask(tileLocation, output_, maxLevel_, this); + task->setYUpAxis(yUpAxis_); + tasks_.append(task); + threadPool_->start(task); } - threadPool->waitForDone(); + threadPool_->waitForDone(); - // 合并子节点 + // merge children tiles BaseTile baseTile; baseTile.geometricError = 2000; - if(yUpAxis) - baseTile.asset.assets["gltfUpAxis"] = "Y"; - else - baseTile.asset.assets["gltfUpAxis"] = "Z"; - + baseTile.asset.assets["gltfUpAxis"] = yUpAxis_ ? "Y" : "Z"; baseTile.asset.assets["version"] = "1.0"; - baseTile.root.transform = Transform::fromXYZ(lon, lat, height); + baseTile.root.transform = Transform::fromXYZ(lon, lat, height_); baseTile.root.geometricError = 1000; - BoundingVolumeBox mergeBox; - for(auto iter = tasks.constBegin(); iter != tasks.constEnd(); ++iter){ - QSharedPointer task = *iter; - if(task->isSucceed){ + OSGBRegion mergeBox; + for(auto iter = tasks_.constBegin(); iter != tasks_.constEnd(); ++iter){ + OSGBConvertTask* task = *iter; + if(task->isSuccess()){ // for this child - RootTile childTile = task->tile.root; - mergeBox = mergeBox.merge(task->tile.root.boundingVolume.box.value()); + RootTile childTile = task->baseTile().root; + mergeBox = mergeBox.merge(task->region()); Content content; - content.uri = "./" + task->osgbLevel.getTileName() + "/tileset.json"; + content.uri = "./" + task->tileName() + "/tileset.json"; childTile.content = content; childTile.children.clear(); baseTile.root.children.append(childTile); } } - baseTile.root.boundingVolume.box = mergeBox; + baseTile.root.boundingVolume.box = mergeBox.toBoundingVolumeBox(); - QFile tilesetjsonFile(output + "/tileset.json"); + QFile tilesetjsonFile(output_ + "/tileset.json"); if(!tilesetjsonFile.open(QIODevice::WriteOnly)){ - qWarning() << "Can't not write tileset.json in " << output; - return; - } - int writeBytes = tilesetjsonFile.write(QJsonDocument(baseTile.write()).toJson(QJsonDocument::Indented)); - if(writeBytes <= 0){ - qWarning() << "Can't not write tileset.json in " << output; + qCritical("can't write tileset.json in %s", output_); return; } + + tilesetjsonFile.write(QJsonDocument(baseTile.write()).toJson(QJsonDocument::Indented)); } } diff --git a/src/OSGBLevel.cpp b/src/OSGBLevel.cpp index 8f029d6..dca0d40 100644 --- a/src/OSGBLevel.cpp +++ b/src/OSGBLevel.cpp @@ -4,79 +4,66 @@ #include #include -#include -#include -#include -#include -#include +#include namespace scially { - - QString OSGBLevel::absoluteLocation() const { - return QDir(nodePath).filePath(nodeName) + OSGBEXTENSION; + QString OSGLevel::getTileName() const { + int p0 = nodeName_.indexOf("_L"); + if (p0 < 0) + return nodeName_; + return nodeName_.left(p0); } - QString OSGBLevel::getTileName() const { - int p0 = nodeName.indexOf("_L"); + int OSGLevel::getLevelNumber() const { + int p0 = nodeName_.indexOf("_L"); if (p0 < 0) - return nodeName; - return nodeName.left(p0); + return 0; + int p1 = nodeName_.indexOf("_", p0 + 1); + if (p1 < 0) + return 0; + return nodeName_.mid(p0 + 2, p1 - p0 - 2).toInt(); } - void OSGBLevel::createDir(const QString& output) const { - for (int i = 0; i < subNodes.size(); i++) { - QDir createDir(output + '/' + subNodes[i].getTileName()); + void OSGLevel::createDir(const QString& output) const { + for (int i = 0; i < subNodes_.size(); i++) { + QDir createDir(output + '/' + subNodes_[i].getTileName()); if (!createDir.exists()) { - if (!createDir.mkpath(".")){ - qWarning() << "Can't create dir: " << createDir.absolutePath(); - } - + if (!createDir.mkpath(".")) + qWarning("can't create dir: %s", createDir.absolutePath()); } } } - int OSGBLevel::getLevelNumber() const { - int p0 = nodeName.indexOf("_L"); - if (p0 < 0) - return 0; - int p1 = nodeName.indexOf("_", p0 + 2); - if (p1 < 0) - return 0; - return nodeName.mid(p0 + 2, p1 - p0 - 2).toInt(); - } - - bool OSGBLevel::getAllOSGBLevels(int maxLevel) { + bool OSGLevel::getAllOSGBLevels(int maxLevel) { if (getLevelNumber() < 0 || getLevelNumber() >= maxLevel) return false; - OSGBPageLodVisitor lodVisitor(nodePath); - - std::vector rootOSGBLocation = { absoluteLocation().toStdString() }; - osg::ref_ptr root = osgDB::readNodeFiles(rootOSGBLocation); - - if (root == nullptr) + OSGBPageLodVisitor lodVisitor(nodePath_); + osg::ref_ptr root = osgDB::readNodeFile(nodeLocation_.toStdString()); + if (root == nullptr) { + qWarning() << "can't read osgb file:" << nodeLocation_; return false; - + } + root->accept(lodVisitor); - for (int i = 0; i < lodVisitor.subNodeNames.size(); i++) { - OSGBLevel subLevel(lodVisitor.subNodeNames[i]); - subLevel.setYUpAxis(yUpAxis); + OSGLevel subLevel(lodVisitor.subNodeNames[i]); + subLevel.setYUpAxis(yUpAxis_); if (subLevel.getAllOSGBLevels(maxLevel)) { - subNodes.append(subLevel); + subNodes_.append(subLevel); } } return true; } - bool OSGBLevel::convertTiles(BaseTile &tile, const QString& output, int maxLevel) { - // + bool OSGLevel::convertTiles(BaseTile &tile, const QString& output, int maxLevel) { if (!getAllOSGBLevels(maxLevel)) { return false; } createDir(output); + // convert tiles and update this region RootTile childTile; if(!convertTiles(childTile, output)){ return false; @@ -85,75 +72,68 @@ namespace scially { //update geometry error updateGeometryError(childTile); - - // update this region - this->region = childTile.boundingVolume.box.value(); - // update root tile tile.geometricError = 2000; - if(yUpAxis) - tile.asset.assets["gltfUpAxis"] = "Y"; - else - tile.asset.assets["gltfUpAxis"] = "Z"; + tile.asset.assets["gltfUpAxis"] = yUpAxis_ ? "Y" : "Z"; tile.asset.assets["version"] = "1.0"; tile.root.children.append(childTile); - tile.root.boundingVolume.box = this->region; + tile.root.boundingVolume.box = this->region_.toBoundingVolumeBox(); tile.root.geometricError = 1000; QFile tilesetFile(output + "/" + getTileName() + "/tileset.json"); if (!tilesetFile.open(QIODevice::WriteOnly)) { - qCritical() << "Can't Write tileset.json in " << tilesetFile.fileName(); + qWarning() << "can't Write tileset.json in" << tilesetFile.fileName(); return false; } - tilesetFile.write(QJsonDocument(tile.write()).toJson(QJsonDocument::Indented)); - return true; + return tilesetFile.write(QJsonDocument(tile.write()).toJson(QJsonDocument::Indented)) > 0; } - bool OSGBLevel::convertTiles(RootTile &root, const QString& output) { - OSGBConvert convert(absoluteLocation()); - convert.yUpAxis = yUpAxis; + bool OSGLevel::convertTiles(RootTile &root, const QString& output) { + OSGBConvert convert(nodeLocation_); + convert.setYUpAxis(yUpAxis_); - QByteArray b3dmBuffer = convert.toB3DM(); - if (b3dmBuffer.isEmpty()) + QByteArray b3dmBuffer; + if (!convert.toB3DM(b3dmBuffer)) return false; - // - QString outputLocation = QDir(output + '/' + getTileName()).absolutePath(); - int writeBytes = convert.writeB3DM(b3dmBuffer, outputLocation); - if (writeBytes <= 0) + + QString outputLocation = QDir::cleanPath(output + '/' + getTileName()); + + if(!convert.writeB3DM(b3dmBuffer, outputLocation)) return false; Content content; - content.uri = "./" + nodeName + B3DMEXTENSION; - content.boundingVolume.box = BoundingVolumeBox(convert.region); + content.uri = "./" + nodeName_ + B3DMEXTENSION; + content.boundingVolume.box = convert.region().toBoundingVolumeBox(); root.refine.type = "REPLACE"; root.content = content; - root.boundingVolume.box = BoundingVolumeBox(convert.region); + root.boundingVolume.box = convert.region().toBoundingVolumeBox(); + + region_ = convert.region(); - for(int i = 0; i < subNodes.size(); i++){ + for(int i = 0; i < subNodes_.size(); i++){ RootTile child; - subNodes[i].convertTiles(child, output); - root.children.append(child); - root.boundingVolume.box = root.boundingVolume.box->merge(child.boundingVolume.box.value()); + if (subNodes_[i].convertTiles(child, output)) { + root.children.append(child); + region_ = region_.merge(subNodes_[i].region()); + } } - + root.boundingVolume.box = region_.toBoundingVolumeBox(); return true; } - void OSGBLevel::updateGeometryError(RootTile &root){ + void OSGLevel::updateGeometryError(RootTile &root){ if(root.children.isEmpty()){ root.geometricError = 0; return; } - else{ - for(auto& tile : root.children) - updateGeometryError(tile); - root.geometricError = root.children[0].boundingVolume.box->geometricError() * 2; - } - + + for(auto& tile : root.children) + updateGeometryError(tile); + + root.geometricError = root.children[0].boundingVolume.box->geometricError() * 2; } - } diff --git a/src/OSGBRegion.cpp b/src/OSGBRegion.cpp new file mode 100644 index 0000000..39ae8f9 --- /dev/null +++ b/src/OSGBRegion.cpp @@ -0,0 +1,82 @@ +#include + +namespace scially { + osg::Vec3d OSGBRegion::getMax() const noexcept { + return osg::Vec3d(west, south, minHeight); + } + osg::Vec3d OSGBRegion::getMin() const noexcept { + return osg::Vec3d(east, north, maxHeight); + } + + void OSGBRegion::setMax(const osg::Vec3d& max) noexcept { + east = max[0]; + north = max[1]; + maxHeight = max[2]; + } + + void OSGBRegion::setMin(const osg::Vec3d& min) noexcept { + west = min[0]; + south = min[1]; + minHeight = min[2]; + } + + void OSGBRegion::setMax(const osg::Vec3f& max) noexcept { + east = max[0]; + north = max[1]; + maxHeight = max[2]; + } + + void OSGBRegion::setMin(const osg::Vec3f& min) noexcept { + west = min[0]; + south = min[1]; + minHeight = min[2]; + } + + void OSGBRegion::mergeMax(const osg::Vec3d& max) noexcept { + osg::Vec3d mergeValue = max < getMax() ? getMax() : max; + setMax(mergeValue); + } + + void OSGBRegion::mergeMin(const osg::Vec3d& min) noexcept { + osg::Vec3d mergeValue = min < getMin() ? min : getMin(); + setMin(mergeValue); + } + + void OSGBRegion::mergeMax(const osg::Vec3f& max) noexcept { + osg::Vec3d _max(max[0], max[1], max[2]); + mergeMax(_max); + } + + void OSGBRegion::mergeMin(const osg::Vec3f& min) noexcept { + osg::Vec3d _min(min[0], min[1], min[2]); + mergeMin(_min); + } + + OSGBRegion OSGBRegion::merge(const OSGBRegion& bounding) const noexcept { + OSGBRegion mergeRegion; + mergeRegion.west = std::min(bounding.west, west); + mergeRegion.east = std::max(bounding.east, east); + mergeRegion.north = std::max(bounding.north, north); + mergeRegion.south = std::min(bounding.south, south); + mergeRegion.minHeight = std::min(bounding.minHeight, minHeight); + mergeRegion.maxHeight = std::max(bounding.maxHeight, maxHeight); + return mergeRegion; + } + + BoundingVolumeBox OSGBRegion::toBoundingVolumeBox() const noexcept { + BoundingVolumeBox box; + box.centerX = (east + west) / 2; + box.centerY = (north + south) / 2; + box.centerZ = (minHeight + maxHeight) / 2; + box.directionX0 = 0 ; + box.directionX1 = 0; + box.halfXLength = (east - west) / 2; + box.directionY0 = 0; + box.directionY1 = 0; + box.halfYLength = (north - south) / 2; + box.directionZ0 = 0; + box.directionZ1 = 0; + box.halfZLength = (maxHeight - minHeight) / 2; + return box; + } +} diff --git a/src/ShpConvert.cpp b/src/ShpConvert.cpp index e791cea..f8ca3bf 100644 --- a/src/ShpConvert.cpp +++ b/src/ShpConvert.cpp @@ -31,8 +31,10 @@ namespace scially { } int heightIndex = layer.GetLayerDefn()->GetFieldIndex(heightField.toStdString().data()); - if (heightIndex == -1) - throw TilesConvertException(heightField + "not found in layer"); + if (heightIndex == -1) { + qCritical() << heightField << "not found in layer"; + return; + } BaseTile tile; double layerMaxHeight = 0; @@ -90,7 +92,7 @@ namespace scially { } } else { - qWarning() << "Only support Polygon(MultiPolygon)"; + qWarning() << "only support Polygon(MultiPolygon)"; } } QByteArray b3dmBuffer = meshes.toB3DM(true); @@ -100,13 +102,13 @@ namespace scially { arg(root->getRow()). arg(root->getCol()); if (!b3dmFile.open(QIODevice::WriteOnly)){ - qWarning() << "Can't write file: " << b3dmFile.fileName(); + qCritical() << "can't write file:" << b3dmFile.fileName(); return; } int writeBytes = b3dmFile.write(b3dmBuffer); if (writeBytes <= 0){ - qWarning() << "Can't write file: " << b3dmFile.fileName(); + qCritical() << "can't write file:" << b3dmFile.fileName(); return; } @@ -139,12 +141,12 @@ namespace scially { QByteArray tileBuffer = QJsonDocument(tile.write()).toJson(); QFile tileFile(output + "/tileset.json"); if (!tileFile.open(QIODevice::WriteOnly)){ - qWarning() << "Can't write file: " << tileFile.fileName(); + qCritical() << "can't write file:" << tileFile.fileName(); return; } int writeBytes = tileFile.write(tileBuffer); if (writeBytes <= 0){ - qWarning() << "Can't write file: " << tileFile.fileName(); + qCritical() << "can't write file:" << tileFile.fileName(); return; } } diff --git a/src/ShpConvertJob.cpp b/src/ShpConvertJob.cpp index 2180efc..f797311 100644 --- a/src/ShpConvertJob.cpp +++ b/src/ShpConvertJob.cpp @@ -5,12 +5,7 @@ namespace scially { void ShpConvertJob::run() { - try{ - ShpConvert convert(input, layerName, height); - convert.convertTiles(output); - }catch(...){ - qCritical() << "Unkown error"; - } - + ShpConvert convert(input, layerName, height); + convert.convertTiles(output); } }