diff --git "a/data/\346\227\245\346\234\254\350\252\236\343\203\221\343\202\271\343\203\206\343\202\271\343\203\210/codelists/DataQualityAttribute_geometrySrcDesc.xml" "b/data/\346\227\245\346\234\254\350\252\236\343\203\221\343\202\271\343\203\206\343\202\271\343\203\210/codelists/DataQualityAttribute_geometrySrcDesc.xml" new file mode 100644 index 00000000..2a4e2ad6 --- /dev/null +++ "b/data/\346\227\245\346\234\254\350\252\236\343\203\221\343\202\271\343\203\206\343\202\271\343\203\210/codelists/DataQualityAttribute_geometrySrcDesc.xml" @@ -0,0 +1,202 @@ + + +DataQualityAttribute_geometrySrcDesc + + +公共測量成果又は基本測量成果 +000 + + + + +(公共測量又は基本測量ではない)現地測量の測量成果 +101 + + + + +(公共測量又は基本測量ではない)UAV写真測量の測量成果 +102 + + + + +(公共測量又は基本測量ではない)空中写真測量の測量成果 +103 + + + + +(公共測量又は基本測量ではない)既成図数値化の測量成果 +104 + + + + +(公共測量又は基本測量ではない)修正測量の測量成果 +105 + + + + +(公共測量又は基本測量ではない)写真地図作成の測量成果 +106 + + + + +(公共測量又は基本測量ではない)地図編集の測量成果 +107 + + + + +(公共測量又は基本測量ではない)地上レーザ測量の測量成果 +108 + + + + +(公共測量又は基本測量ではない)UAV写真点群測量の測量成果 +109 + + + + +(公共測量又は基本測量ではない)UAVレーザ測量の測量成果 +110 + + + + +(公共測量又は基本測量ではない)車載写真レーザ測量の測量成果 +111 + + + + +(公共測量又は基本測量ではない)航空レーザ測量の測量成果 +112 + + + + +(公共測量又は基本測量ではない)航空レーザ測深測量の測量成果 +113 + + + + +(公共測量又は基本測量ではない)路線測量の測量成果 +114 + + + + +(公共測量又は基本測量ではない)河川測量の測量成果 +115 + + + + +(公共測量又は基本測量ではない)用地測量の測量成果 +116 + + + + +(公共測量又は基本測量ではない)その他の応用測量の測量成果 +117 + + + + +(公共測量又は基本測量ではない)LidarSLAM計測の測量成果 +118 + + + + +(公共測量又は基本測量ではない)高密度航空レーザ測量の測量成果 +119 + + + + +(公共測量又は基本測量ではない)写真点群測量の測量成果 +120 + + + + +(公共測量又は基本測量ではない)三次元数値図化の測量成果 +121 + + + + +都市計画基礎調査 +201 + + + + +都市計画図書 +202 + + + + +台帳 +300 + + + + +道路台帳 +301 + + + + +その他のGISデータ +400 + + + + +BIMモデル、CADデータ、設計図、完成図、一般図(平面図、配置図、断面図等) +500 + + + + +その他の資料 +700 + + + + +現地調査 +801 + + + + +GISデータ演算 +803 + + + + +推定 +901 + + + + +未作成 +999 + + + diff --git "a/data/\346\227\245\346\234\254\350\252\236\343\203\221\343\202\271\343\203\206\343\202\271\343\203\210/codelists/DataQualityAttribute_thematicSrcDesc.xml" "b/data/\346\227\245\346\234\254\350\252\236\343\203\221\343\202\271\343\203\206\343\202\271\343\203\210/codelists/DataQualityAttribute_thematicSrcDesc.xml" new file mode 100644 index 00000000..4551b888 --- /dev/null +++ "b/data/\346\227\245\346\234\254\350\252\236\343\203\221\343\202\271\343\203\206\343\202\271\343\203\210/codelists/DataQualityAttribute_thematicSrcDesc.xml" @@ -0,0 +1,106 @@ + + +DataQualityAttribute_thematicSrcDesc + + +公共測量成果又は基本測量成果 +000 + + + + +基盤地図情報 +022 + + + + +数値地形図データ +023 + + + + +公共測量成果又は基本測量成果ではない測量成果 +100 + + + + +都市計画基礎調査 +201 + + + + +都市計画図書 +202 + + + + +台帳 +300 + + + + +道路台帳 +301 + + + + +その他のGISデータ +400 + + + + +BIMモデル、CADデータ、設計図、完成図、一般図(平面図、配置図、断面図等) +500 + + + + +統計データ +600 + + + + +建築計画概要書 +701 + + + + +その他の資料 +700 + + + + +現地調査 +801 + + + + +写真判読 +802 + + + + +GISデータ演算 +803 + + + + +未作成 +999 + + + diff --git a/include/plateau/dataset/gml_file.h b/include/plateau/dataset/gml_file.h index 6e7c5a0f..8481a0b5 100644 --- a/include/plateau/dataset/gml_file.h +++ b/include/plateau/dataset/gml_file.h @@ -27,7 +27,6 @@ namespace plateau::dataset { */ GridCode* getGridCodeRaw() const; double getEpsg() const; - bool isPolarCoordinateSystem() const; const std::string& getFeatureType() const; PredefinedCityModelPackage getPackage() const; std::string getAppearanceDirectoryPath() const; diff --git a/include/plateau/geometry/geo_coordinate.h b/include/plateau/geometry/geo_coordinate.h index 1dc4cf7b..54a41555 100644 --- a/include/plateau/geometry/geo_coordinate.h +++ b/include/plateau/geometry/geo_coordinate.h @@ -2,7 +2,9 @@ #include "citygml/vecs.hpp" #include "citygml/cityobject.h" - +#include +#include +#include namespace plateau::geometry { @@ -78,6 +80,19 @@ namespace plateau::geometry { */ bool contains(const citygml::CityObject& city_obj, bool ignore_height = true) const; + /** + * 座標系のEPSGコードに応じて適切な座標変換を行い、点が範囲内に含まれるかを判定します。 + * 平面直角座標系(EPSG 10162~10174)の場合は、平面座標を緯度経度座標に変換してから判定します。 + * 極座標系(それ以外のEPSG)の場合は、通常のcontainsメソッドと同様に直接判定します。 + * + * @param point 判定対象の点 + * @param epsg 座標系を識別するEPSGコード + * @param ignore_height 高さを無視する場合はtrue + * @return 点が範囲内に含まれる場合はtrue + */ + bool containsInPolar(TVec3d point,const int epsg, bool ignore_height = true) const; + bool containsInPolar(const citygml::CityObject& city_obj,const int epsg, bool ignore_height = true) const; + /** * other と交わる箇所があるかどうかを返します。 * ただし other の高さは無視して緯度と経度の2次元のみで判定します。 @@ -94,9 +109,59 @@ namespace plateau::geometry { static Extent all() { return { - GeoCoordinate(-9999999, -9999999, -9999), - GeoCoordinate(9999999, 9999999, 9999) + GeoCoordinate(-90, -180, -9999), + GeoCoordinate(90, 180, 9999) }; } }; + + /** + * 平面直角座標系の判定、平面直角座標の基準点取得 + */ + struct CoordinateReferenceFactory { + static constexpr int default_epsg = 6697; + // EPSGとZone IDのマッピング + static const std::unordered_map epsg_to_zone; + // Zone IDごとの座標データ + static const std::unordered_map> zone_to_point; + // EPSGごとのzone取得 + static int GetZoneId(int epsg) { + auto it = epsg_to_zone.find(epsg); + if (it != epsg_to_zone.end()) { + return it->second; + } + return 0; + } + // EPSGごとの基準点取得 + static GeoCoordinate GetOriginPoint(int epsg) { + const int zone = GetZoneId(epsg); + if (zone != 0) { + auto it = zone_to_point.find(zone); + if (it != zone_to_point.end()) { + const auto& coords = it->second; + return GeoCoordinate(coords[0], coords[1], coords[2]); + } + } + return GeoCoordinate(); + } + // 極座標系・平面直角座標系判定 + static bool IsPolarCoordinateSystem(int epsg) { + // 平面直角座標系(EPSG 10162~10174)かどうかを明示的に確認 + return epsg_to_zone.find(epsg) == epsg_to_zone.end(); + } + }; + // EPSGとZone IDのマッピング + inline const std::unordered_map CoordinateReferenceFactory::epsg_to_zone = { + {10162, 1}, {10163, 2}, {10164, 3}, {10165, 4}, {10166, 5}, + {10167, 6}, {10168, 7}, {10169, 8}, {10170, 9}, {10171, 10}, + {10172, 11}, {10173, 12}, {10174, 13} + }; + // Zone IDごとの座標データ + inline const std::unordered_map> CoordinateReferenceFactory::zone_to_point = { + {1, {33.0, 129.5, 0.0}}, {2, {33.0, 131.0, 0.0}}, {3, {36.0, 132.166667, 0.0}}, + {4, {33.0, 133.5, 0.0}}, {5, {36.0, 134.333333, 0.0}}, {6, {36.0, 136.0, 0.0}}, + {7, {36.0, 137.166667, 0.0}}, {8, {36.0, 138.5, 0.0}}, {9, {35.0, 139.833333, 0.0}}, + {10, {40.0, 140.833333, 0.0}}, {11, {44.0, 140.25, 0.0}}, {12, {44.0, 142.0, 0.0}}, + {13, {43.0, 144.0, 0.0}} + }; } diff --git a/include/plateau/geometry/geo_reference.h b/include/plateau/geometry/geo_reference.h index 52ca6680..a527c8ab 100644 --- a/include/plateau/geometry/geo_reference.h +++ b/include/plateau/geometry/geo_reference.h @@ -26,10 +26,13 @@ namespace plateau::geometry { /// project の座標軸変換をしない版です。座標軸は ENU → ENU であるとします。 reference_point_ は ENUに変換されます。 TVec3d projectWithoutAxisConvert(const TVec3d& lat_lon) const; TVec3d convertAxisToENU(const TVec3d& vertex) const; - TVec3d convert(const TVec3d& lat_lon, const bool convert_axis = true, const bool project = true) const; + TVec3d convert(const TVec3d& lat_lon, const bool convert_axis = true, const int epsg = CoordinateReferenceFactory::default_epsg) const; static TVec3d convertAxisFromENUTo(CoordinateSystem axis, const TVec3d& vertex); static TVec3d convertAxisToENU(CoordinateSystem axis, const TVec3d& vertex); + static TVec3d reverseXY(const TVec3d& vertex); + static GeoCoordinate planeToPolar(const TVec3d& vertex, const int coordinate_zone_id); + GeoCoordinate unproject(const TVec3d& point) const; void setReferencePoint(TVec3d point); diff --git a/include/plateau/polygon_mesh/mesh_extract_options.h b/include/plateau/polygon_mesh/mesh_extract_options.h index ec72c522..2fb8e923 100644 --- a/include/plateau/polygon_mesh/mesh_extract_options.h +++ b/include/plateau/polygon_mesh/mesh_extract_options.h @@ -37,7 +37,8 @@ namespace plateau::polygonMesh { texture_packing_resolution(2048), attach_map_tile(true), map_tile_zoom_level(15), - map_tile_url("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg") + map_tile_url("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg"), + epsg_code(plateau::geometry::CoordinateReferenceFactory::default_epsg) {} public: @@ -111,5 +112,10 @@ namespace plateau::polygonMesh { * https://ctrlshift.hatenadiary.org/entry/20080119/1200719590 */ char map_tile_url[1000]; + + /** + * 平面直角座標系は、EPSGコードに応じて基準点を取得します。 + */ + int epsg_code; }; } diff --git a/src/c_wrapper/geo_reference_c.cpp b/src/c_wrapper/geo_reference_c.cpp index c4eb3d55..8a0d8033 100644 --- a/src/c_wrapper/geo_reference_c.cpp +++ b/src/c_wrapper/geo_reference_c.cpp @@ -22,10 +22,10 @@ extern "C" { GeoReference) DLL_VALUE_FUNC(plateau_geo_reference_project, - GeoReference, - TVec3d, - handle->project(lat_lon), - , GeoCoordinate lat_lon) + GeoReference, + TVec3d, + handle->project(lat_lon), + , GeoCoordinate lat_lon) DLL_VALUE_FUNC(plateau_geo_reference_unproject, GeoReference, @@ -33,6 +33,24 @@ extern "C" { handle->unproject(point), , TVec3d point) + DLL_VALUE_FUNC(plateau_geo_reference_project_point, + GeoReference, + TVec3d, + handle->project(point), + , TVec3d point) + + DLL_VALUE_FUNC(plateau_geo_reference_project_without_axis_convert, + GeoReference, + TVec3d, + handle->projectWithoutAxisConvert(point), + , TVec3d point) + + DLL_VALUE_FUNC(plateau_geo_reference_convert, + GeoReference, + TVec3d, + handle->convert(point, convert_axis, epsg), + , TVec3d point, bool convert_axis, int epsg) + DLL_VALUE_FUNC(plateau_geo_reference_get_reference_point, GeoReference, TVec3d, diff --git a/src/c_wrapper/geometry_utils_c.cpp b/src/c_wrapper/geometry_utils_c.cpp index c49f3f82..17268706 100644 --- a/src/c_wrapper/geometry_utils_c.cpp +++ b/src/c_wrapper/geometry_utils_c.cpp @@ -1,8 +1,10 @@ #include "libplateau_c.h" #include "city_model_c.h" #include +#include using namespace libplateau; using namespace plateau::polygonMesh; +using namespace plateau::geometry; extern "C" { @@ -12,4 +14,15 @@ DLL_VALUE_FUNC(plateau_geometry_utils_get_center_point, PolygonMeshUtils::getCenterPoint(*handle->getCityModelPtr(), coordinate_zone_id), ,int coordinate_zone_id) +LIBPLATEAU_C_EXPORT APIResult LIBPLATEAU_C_API plateau_geometry_utils_is_polar_coordinate_system( + int epsg, + bool* out +) { +API_TRY{ + *out = CoordinateReferenceFactory::IsPolarCoordinateSystem(epsg); + return APIResult::Success; +} API_CATCH + return APIResult::ErrorUnknown; +} + } diff --git a/src/c_wrapper/gml_file_c.cpp b/src/c_wrapper/gml_file_c.cpp index bb896570..c5daaddb 100644 --- a/src/c_wrapper/gml_file_c.cpp +++ b/src/c_wrapper/gml_file_c.cpp @@ -40,14 +40,19 @@ extern "C" { } DLL_STRING_PTR_FUNC(plateau_gml_file_get_feature_type_str, - GmlFile, - handle->getFeatureType()) + GmlFile, + handle->getFeatureType()) DLL_PTR_FUNC(plateau_gml_file_get_grid_code, GmlFile, GridCode, handle->getGridCodeRaw()) + DLL_VALUE_FUNC(plateau_gml_file_get_epsg, + GmlFile, + int, + handle->getEpsg()) + LIBPLATEAU_C_EXPORT APIResult LIBPLATEAU_C_API plateau_gml_file_fetch( const GmlFile* const gml_file_info, char* destination_root_path_chars, diff --git a/src/dataset/gml_file.cpp b/src/dataset/gml_file.cpp index 233a409f..b4a81176 100644 --- a/src/dataset/gml_file.cpp +++ b/src/dataset/gml_file.cpp @@ -54,25 +54,15 @@ namespace plateau::dataset { return GridCode::createRaw(grid_code_->get()); } - double GmlFile::getEpsg() const { + double GmlFile::getEpsg() const { try { - return epsg_.empty() ? 6697 : std::stod(epsg_); + return epsg_.empty() ? plateau::geometry::CoordinateReferenceFactory::default_epsg : std::stod(epsg_); } catch (const std::exception&) { - return 6697; + return plateau::geometry::CoordinateReferenceFactory::default_epsg; } } - bool GmlFile::isPolarCoordinateSystem() const { - double epsg = getEpsg(); - // 平面直角座標系の区分についてはこちらを参照してください : - // https://www.mlit.go.jp/plateaudocument/toc9/toc9_08/toc9_08_04/ - if (epsg >= 10162 && epsg <= 10174) { - return false; - } - return true; - } - const std::string& GmlFile::getFeatureType() const { return feature_type_; } diff --git a/src/geometry/geo_coordinate.cpp b/src/geometry/geo_coordinate.cpp index 090a92d7..c8f5ab6c 100644 --- a/src/geometry/geo_coordinate.cpp +++ b/src/geometry/geo_coordinate.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -63,6 +64,32 @@ namespace plateau::geometry { } } + bool Extent::containsInPolar(TVec3d point, const int epsg, bool ignore_height) const { + + if (!CoordinateReferenceFactory::IsPolarCoordinateSystem(epsg)) { + // 平面直角座標系の判定 + const auto& unprojected = GeoReference::planeToPolar(point, CoordinateReferenceFactory::GetZoneId(epsg)); + point = { unprojected.latitude, unprojected.longitude, unprojected.height }; + } + return contains(GeoCoordinate(point.x, point.y, point.z), ignore_height); + } + + bool Extent::containsInPolar(const CityObject& city_obj, const int epsg, bool ignore_height) const { + + if (!CoordinateReferenceFactory::IsPolarCoordinateSystem(epsg)) { + // 平面直角座標系の判定 + try { + const auto pos = PolygonMeshUtils::cityObjPos(city_obj); + return containsInPolar(pos, epsg, ignore_height); + } + catch (std::invalid_argument& e) { + // 位置不明は false 扱いとします。 + return false; + } + } + return contains(city_obj, ignore_height); + } + bool Extent::intersects2D(const Extent& other) const { const auto center_1 = centerPoint(); const auto center_2 = other.centerPoint(); diff --git a/src/geometry/geo_reference.cpp b/src/geometry/geo_reference.cpp index 641d01c5..8c04eba3 100644 --- a/src/geometry/geo_reference.cpp +++ b/src/geometry/geo_reference.cpp @@ -24,18 +24,26 @@ namespace plateau::geometry { return converted_point; } - TVec3d GeoReference::convert(const TVec3d& lat_lon, const bool convert_axis, const bool project) const { + //平面直角座標判定を含むproject, projectWithoutAxisConvert処理と同様の処理 + TVec3d GeoReference::convert(const TVec3d& lat_lon, const bool convert_axis, const int epsg) const { //平面直角座標変換、座標軸変換をフラグに応じてスキップします。 TVec3d point = lat_lon; - // 平面直角座標系に変換 - if (project) - PolarToPlaneCartesian().project(point, zone_id_); + + // 極座標系・平面直角座標系判定 + const bool is_polar = CoordinateReferenceFactory::IsPolarCoordinateSystem(epsg); + if (!is_polar) { + //平面直角座標の場合は緯度経度に変換 + const auto& unprojected = planeToPolar(point, CoordinateReferenceFactory::GetZoneId(epsg)); + point = { unprojected.latitude, unprojected.longitude, unprojected.height }; + } + + PolarToPlaneCartesian().project(point, zone_id_); if (!convert_axis) { - // 座標軸変換をしない場合 + // 座標軸変換をしない場合 TVec3 converted_point = point / unit_scale_ - convertAxisToENU(coordinate_system_, reference_point_); return converted_point; } - // 座標軸変換をする場合 + // 座標軸変換をする場合 TVec3 converted_point = convertAxisFromENUTo(coordinate_system_, point); converted_point = converted_point / unit_scale_ - reference_point_; return converted_point; @@ -88,6 +96,20 @@ namespace plateau::geometry { } } + //平面直角座標のGMLの座標は xyが反転しているので変換 + TVec3d GeoReference::reverseXY(const TVec3d& vertex) { + return { vertex.y, vertex.x, vertex.z }; //x,y反転 + } + + //平面直角座標から緯度経度に変換 + GeoCoordinate GeoReference::planeToPolar(const TVec3d& vertex, const int coordinate_zone_id) { + TVec3d point = vertex; + point = reverseXY(point); + plateau::geometry::GeoReference geo_ref(coordinate_zone_id); + const auto unprojected = geo_ref.unproject(point); + return unprojected; + } + void GeoReference::setReferencePoint(TVec3d point) { reference_point_ = point; } diff --git a/src/polygon_mesh/area_mesh_factory.cpp b/src/polygon_mesh/area_mesh_factory.cpp index 46e14429..af42f28a 100644 --- a/src/polygon_mesh/area_mesh_factory.cpp +++ b/src/polygon_mesh/area_mesh_factory.cpp @@ -7,6 +7,7 @@ namespace { using namespace plateau; using namespace polygonMesh; + using namespace geometry; /** * グリッド番号と、そのグリッドに属する CityObject のリストを対応付ける辞書です。 @@ -19,7 +20,7 @@ namespace { return false; for (const auto& extent : extents) { - if (extent.contains(city_obj)) + if (extent.containsInPolar(city_obj, options.epsg_code)) return false; } diff --git a/src/polygon_mesh/mesh_extractor.cpp b/src/polygon_mesh/mesh_extractor.cpp index 01791659..d70a9139 100644 --- a/src/polygon_mesh/mesh_extractor.cpp +++ b/src/polygon_mesh/mesh_extractor.cpp @@ -25,9 +25,9 @@ namespace { // 範囲外を省く設定ならば省きます。 if (!options.exclude_city_object_outside_extent) return false; - + for (const auto& extent : extents) { - if (extent.contains(city_obj)) + if (extent.containsInPolar(city_obj, options.epsg_code)) return false; } return true; diff --git a/src/polygon_mesh/mesh_factory.cpp b/src/polygon_mesh/mesh_factory.cpp index f03579fd..f72db6f3 100644 --- a/src/polygon_mesh/mesh_factory.cpp +++ b/src/polygon_mesh/mesh_factory.cpp @@ -32,9 +32,7 @@ namespace plateau::polygonMesh { */ void cityGmlPolygonToMesh( const Polygon& polygon, const std::string& gml_path, - const GeoReference& geo_reference, Mesh& out_mesh) { - - const auto& gml = plateau::dataset::GmlFile(gml_path); + const GeoReference& geo_reference, Mesh& out_mesh, int epsg) { // マージ対象の情報を取得します。ここでの頂点は極座標です。 const auto& vertices_lat_lon = polygon.getVertices(); @@ -56,7 +54,7 @@ namespace plateau::polygonMesh { auto& out_vertices = out_mesh.getVertices(); out_vertices.reserve(vertices_lat_lon.size()); for (const auto& lat_lon : vertices_lat_lon) { - auto xyz = geo_reference.convert(lat_lon, false, gml.isPolarCoordinateSystem()); + auto xyz = geo_reference.convert(lat_lon, false, epsg); out_vertices.push_back(xyz); } assert(out_vertices.size() == vertices_lat_lon.size()); @@ -130,12 +128,12 @@ namespace plateau::polygonMesh { void findAllPolygonsInGeometry( const Geometry& geom, std::list& polygons, const unsigned lod, long long& out_vertices_count, - const std::vector extents) { + const std::vector& extents, const MeshExtractOptions& options) { // 子のジオメトリのポリゴンをすべて取得 const unsigned int child_count = geom.getGeometriesCount(); for (unsigned int i = 0; i < child_count; i++) { - findAllPolygonsInGeometry(geom.getGeometry(i), polygons, lod, out_vertices_count, extents); + findAllPolygonsInGeometry(geom.getGeometry(i), polygons, lod, out_vertices_count, extents, options); } if (geom.getLOD() != lod) return; @@ -148,7 +146,7 @@ namespace plateau::polygonMesh { // TODO: 計算コストが頂点数と範囲数に比例するため高速化 for (const auto& vertex : polygon->getVertices()) { for (const auto& extent : extents) { - if (extent.contains(vertex)) { + if (extent.containsInPolar(vertex, options.epsg_code)) { is_in_extent = true; break; } @@ -206,7 +204,7 @@ namespace plateau::polygonMesh { return; Mesh mesh; - cityGmlPolygonToMesh(polygon, gml_path, geo_reference_, mesh); + cityGmlPolygonToMesh(polygon, gml_path, geo_reference_, mesh, options_.epsg_code); const auto from_axis = geometry::CoordinateSystem::ENU; const auto to_axis = options_.mesh_axes; @@ -349,11 +347,11 @@ namespace plateau::polygonMesh { std::vector extents = { Extent::all() }; if (options_.exclude_polygons_outside_extent) extents = extents_; - + for (unsigned i = 0; i < geometry_count; i++) { findAllPolygonsInGeometry( city_obj.getGeometry(i), out_polygons, lod, - out_vertices_count, extents); + out_vertices_count, extents, options_); } } diff --git a/src/polygon_mesh/polygon_mesh_utils.cpp b/src/polygon_mesh/polygon_mesh_utils.cpp index 4ff9f853..e8cb6e24 100644 --- a/src/polygon_mesh/polygon_mesh_utils.cpp +++ b/src/polygon_mesh/polygon_mesh_utils.cpp @@ -1,6 +1,7 @@ #include #include "plateau/polygon_mesh/mesh.h" #include "plateau/geometry/geo_reference.h" +#include "plateau/geometry/geo_coordinate.h" #include "citygml/citymodel.h" #include @@ -60,9 +61,9 @@ namespace plateau::polygonMesh { if (!envelope.validBounds()) { return TVec3d{0, 0, 0}; } - const auto& gml = plateau::dataset::GmlFile(city_model.getGmlPath()); + const auto& gml = plateau::dataset::GmlFile(city_model.getGmlPath()); // 平面直角座標系の判定用 auto city_center = (envelope.getLowerBound() + envelope.getUpperBound()) / 2.0; - return geometry::GeoReference(coordinate_zone_id).convert(city_center, true, gml.isPolarCoordinateSystem()); + return geometry::GeoReference(coordinate_zone_id).convert(city_center, true, gml.getEpsg()); } /** diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4ca91885..b54f851d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,6 +50,7 @@ add_executable(plateau_test "test_heightmap_mesh_generator.cpp" "test_standard_map_grid.cpp" "test_geo_reference.cpp" + "test_geo_coordinate.cpp" ) add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/test_granularity_convert") diff --git a/test/test_geo_coordinate.cpp b/test/test_geo_coordinate.cpp new file mode 100644 index 00000000..395c2227 --- /dev/null +++ b/test/test_geo_coordinate.cpp @@ -0,0 +1,59 @@ +#include +#include "../src/geometry/geo_coordinate.cpp" + +namespace plateau::geometry { + class GeoCoordinateTest : public ::testing::Test { + protected: + }; + + TEST_F(GeoCoordinateTest, ExtentContains) { // NOLINT + + plateau::geometry::Extent ext(GeoCoordinate(-30, -90, -9999), GeoCoordinate(30, 90, 9999)); + plateau::geometry::Extent ext2(GeoCoordinate(-30, -90, -9999), GeoCoordinate(60, 180, 9999)); + + ASSERT_TRUE(ext.contains(TVec3d(0, 0, 0))); + ASSERT_TRUE(ext.contains(GeoCoordinate(1,1,0))); + ASSERT_FALSE(ext.contains(GeoCoordinate(40, 0, 0))); + ASSERT_FALSE(ext.contains(GeoCoordinate(0, -100, 0))); + + // 極座標系EPSG:6697(日本測地系2000)の場合、containsとcontainsInPolarの結果が一致することを確認 + ASSERT_EQ(ext.contains(TVec3d(0, 0, 0)), ext.containsInPolar(TVec3d(0, 0, 0), 6697)); + ASSERT_EQ(ext.contains(TVec3d(80, 90, 0)), ext.containsInPolar(TVec3d(80, 90, 0), 6697)); + + // 平面直角座標 + // EPSG:10169は平面直角座標系(第8系) + const auto& zoneRefPoint = GeoReference::planeToPolar(TVec3d(), 8); + ASSERT_FLOAT_EQ(36.0, zoneRefPoint.latitude); + ASSERT_FLOAT_EQ(138.5, zoneRefPoint.longitude); + ASSERT_FALSE(ext.containsInPolar(TVec3d(), 10169)); + ASSERT_TRUE(ext2.containsInPolar(TVec3d(), 10169)); + } + + TEST_F(GeoCoordinateTest, CoordinateReference) { // NOLINT + + // 正常系テスト - EPSGから正しいゾーンIDが取得できること + ASSERT_EQ(1, CoordinateReferenceFactory::GetZoneId(10162)); // 最小値 + ASSERT_EQ(8, CoordinateReferenceFactory::GetZoneId(10169)); // 中間値 + ASSERT_EQ(13, CoordinateReferenceFactory::GetZoneId(10174)); // 最大値 + + // 異常系テスト - 範囲外のEPSGでは0が返されること + ASSERT_EQ(0, CoordinateReferenceFactory::GetZoneId(10161)); // 境界外(最小値-1) + ASSERT_EQ(0, CoordinateReferenceFactory::GetZoneId(10175)); // 境界外(最大値+1) + ASSERT_EQ(0, CoordinateReferenceFactory::GetZoneId(6697)); // 極座標系EPSG + + ASSERT_FALSE(CoordinateReferenceFactory::IsPolarCoordinateSystem(10169)); + ASSERT_TRUE(CoordinateReferenceFactory::IsPolarCoordinateSystem(6697)); + ASSERT_TRUE(CoordinateReferenceFactory::IsPolarCoordinateSystem(4301)); // JGD2000 + ASSERT_TRUE(CoordinateReferenceFactory::IsPolarCoordinateSystem(0)); // 不明なEPSG + + const auto& refPoint = CoordinateReferenceFactory::GetOriginPoint(10169); + ASSERT_FLOAT_EQ(36.0, refPoint.latitude); + ASSERT_FLOAT_EQ(138.5, refPoint.longitude); + + // 無効なEPSGの場合、空のGeoCoordinateが返されること + const auto & invalidRefPoint = CoordinateReferenceFactory::GetOriginPoint(0); + ASSERT_FLOAT_EQ(0.0, invalidRefPoint.latitude); + ASSERT_FLOAT_EQ(0.0, invalidRefPoint.longitude); + ASSERT_FLOAT_EQ(0.0, invalidRefPoint.height); + } +} diff --git a/test/test_geo_reference.cpp b/test/test_geo_reference.cpp index 3b1c81b6..27e80285 100644 --- a/test/test_geo_reference.cpp +++ b/test/test_geo_reference.cpp @@ -20,9 +20,9 @@ namespace plateau::geometry { TVec3d base_point = TVec3d(100, 100, 0); }; - TEST_F(GeoReferenceTest, ConvertAxisProject) { // NOLINT + TEST_F(GeoReferenceTest, ConvertAxisPolar) { // NOLINT // 平面直角座標変換・座標軸変換を行う - TVec3d converted = ref.convert(base_point, true, true); + TVec3d converted = ref.convert(base_point, true, 6697); TVec3d projected = ref.project(base_point); // Expected @@ -35,9 +35,9 @@ namespace plateau::geometry { ASSERT_EQ(expected_point, projected); } - TEST_F(GeoReferenceTest, ConvertProjectOnly) { // NOLINT + TEST_F(GeoReferenceTest, ConvertProjectPolar) { // NOLINT // 平面直角座標変換を行う・座標軸変換を行わない - TVec3d converted = ref.convert(base_point, false, true); + TVec3d converted = ref.convert(base_point, false, 6697); TVec3d projected = ref.projectWithoutAxisConvert(base_point); // Expected @@ -49,27 +49,48 @@ namespace plateau::geometry { ASSERT_EQ(expected_point, projected); } - TEST_F(GeoReferenceTest, ConvertAxisOnly) { // NOLINT - // 平面直角座標変換を行わない・座標軸変換を行う - TVec3d point = ref.convert(base_point, true, false); + TEST_F(GeoReferenceTest, ConvertAxisPlane) { // NOLINT + // 平面->緯度経度->平面変換・座標軸変換を行う + TVec3d point = ref.convert(base_point, true, 10169); // Expected - TVec3 expected_point = GeoReference::convertAxisFromENUTo(coordinate, base_point); + TVec3d position = base_point; + const auto& unprj = GeoReference::planeToPolar(position, CoordinateReferenceFactory::GetZoneId(10169)); + position = { unprj.latitude, unprj.longitude, unprj.height }; + PolarToPlaneCartesian().project(position, zone_id); + TVec3 expected_point = GeoReference::convertAxisFromENUTo(coordinate, position); expected_point = expected_point / unit_scale - ref_point; ASSERT_EQ(expected_point, point); } - TEST_F(GeoReferenceTest, ConvertOnly) { // NOLINT - // 平面直角座標変換・座標軸変換を行わない - TVec3d point = ref.convert(base_point, false, false); + TEST_F(GeoReferenceTest, ConvertPlane) { // NOLINT + // 平面->緯度経度->平面変換を行う・座標軸変換を行わない + TVec3d point = ref.convert(base_point, false, 10169); // Expected - TVec3 expected_point = base_point / unit_scale - GeoReference::convertAxisToENU(coordinate, ref_point); + TVec3d position = base_point; + const auto& unprj = GeoReference::planeToPolar(position, CoordinateReferenceFactory::GetZoneId(10169)); + position = { unprj.latitude, unprj.longitude, unprj.height }; + PolarToPlaneCartesian().project(position, zone_id); + TVec3 expected_point = position / unit_scale - GeoReference::convertAxisToENU(coordinate, ref_point); ASSERT_EQ(expected_point, point); } - // fetch のテストは test_dataset.cpp にあります。 + // 平面直角座標のGMLの値を緯度経度に変換 + TEST_F(GeoReferenceTest, PlaneToPolarConversion) { // NOLINT + TVec3d base_position(100, -100, 1); // 経度、緯度、高さ + + const auto& polar = GeoReference::planeToPolar(base_position, 9); + TVec3d polar_vector = { polar.latitude, polar.longitude, polar.height }; + + // xy反転してunprojectした値 + TVec3d position = { base_position.y, base_position.x, base_position.z }; // xy反転 + PolarToPlaneCartesian().unproject(position, 9); + const auto& expected_point = position; + + ASSERT_EQ(expected_point, polar_vector); + } } diff --git a/test/test_gml_file.cpp b/test/test_gml_file.cpp index 1acb51a1..8302176d 100644 --- a/test/test_gml_file.cpp +++ b/test/test_gml_file.cpp @@ -16,11 +16,11 @@ namespace plateau::dataset { TEST_F(GmlFileTest, get_epsg) { // NOLINT auto info1 = GmlFile(std::string("foobar/udx/unf/08EE751_unf_10169_water_op.gml")); ASSERT_EQ(10169, info1.getEpsg()); - ASSERT_FALSE(info1.isPolarCoordinateSystem()); + ASSERT_FALSE(plateau::geometry::CoordinateReferenceFactory::IsPolarCoordinateSystem(info1.getEpsg())); auto info2 = GmlFile(std::string("foobar/udx/bldg/53392546_bldg_6697_2_op.gml")); ASSERT_EQ(6697, info2.getEpsg()); - ASSERT_TRUE(info2.isPolarCoordinateSystem()); + ASSERT_TRUE(plateau::geometry::CoordinateReferenceFactory::IsPolarCoordinateSystem(info2.getEpsg())); } // fetch のテストは test_dataset.cpp にあります。 diff --git a/test/test_mesh_extractor.cpp b/test/test_mesh_extractor.cpp index 250320cc..a9ea3905 100644 --- a/test/test_mesh_extractor.cpp +++ b/test/test_mesh_extractor.cpp @@ -204,29 +204,38 @@ namespace plateau::polygonMesh { } } - // Epsgが6697以外(10162~10174)の場合、平面直角座標変換を行わない + // Epsgが6697以外(10162~10174)の場合、GMLの位置情報が平面直角座標 TEST_F(MeshExtractorTest, no_coordinate_transformation_during_conversion) { // NOLINT const std::string gml_path = u8"../data/日本語パステスト/udx/unf/08EE763_unf_10169_sewer_op.gml"; ParserParams params; params.tesselate = true; - MeshExtractOptions mesh_extract_options = MeshExtractOptions(); + + const std::shared_ptr city_model = load(gml_path, params); + const auto& gml = plateau::dataset::GmlFile((city_model->getGmlPath())); + const auto& epsg = gml.getEpsg(); + const auto& zone = CoordinateReferenceFactory::GetZoneId(epsg); + ASSERT_EQ(10169, epsg); + ASSERT_FALSE(plateau::geometry::CoordinateReferenceFactory::IsPolarCoordinateSystem(epsg)); + ASSERT_EQ(8, zone); + + MeshExtractOptions mesh_extract_options = MeshExtractOptions(); mesh_extract_options.min_lod = 0; mesh_extract_options.max_lod = 2; mesh_extract_options.mesh_granularity = MeshGranularity::PerPrimaryFeatureObject; mesh_extract_options.grid_count_of_side = 5; mesh_extract_options.exclude_city_object_outside_extent = true; mesh_extract_options.exclude_polygons_outside_extent = false; - mesh_extract_options.coordinate_zone_id = 8; - mesh_extract_options.unit_scale = 1.0; + mesh_extract_options.coordinate_zone_id = zone; + mesh_extract_options.unit_scale = 1.0; mesh_extract_options.mesh_axes = CoordinateSystem::ENU; - const std::shared_ptr city_model = load(gml_path, params); - - const auto& gml = plateau::dataset::GmlFile((city_model->getGmlPath())); - ASSERT_FALSE(gml.isPolarCoordinateSystem()); + mesh_extract_options.epsg_code = epsg; + // Extracted Model auto model = MeshExtractor::extract(*city_model, mesh_extract_options); + ASSERT_GE(model->getRootNodeCount(),1); const auto& lod_node = model->getRootNodeAt(0); + ASSERT_GE(lod_node.getChildCount(),1); const auto& first_model_node = lod_node.getChildAt(0); const auto& mesh = first_model_node.getMesh(); @@ -240,11 +249,15 @@ namespace plateau::polygonMesh { const auto& city_model_polygon = root_geometry.getPolygon(0); const auto& city_model_vertices = city_model_polygon->getVertices(); - // 変換されないのでscale:1でENUであればCityModelと座標が同じになる + // scale:1でENUであればCityModelとほぼ同一座標 + // 平面直角座標は、XYZ => YXZの変換が行われる for (int i = 0; i < city_model_vertices.size(); i++) { const auto& city_model_vertex = city_model_vertices[i]; const auto& vertex = vertices[i]; - ASSERT_EQ(vertex, city_model_vertex); + + ASSERT_NEAR(vertex.y, city_model_vertex.x, 0.1); + ASSERT_NEAR(vertex.x, city_model_vertex.y, 0.1); + ASSERT_NEAR(vertex.z, city_model_vertex.z, 0.1); } } diff --git a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs index 3e2e0e87..9ed055cc 100644 --- a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs +++ b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs @@ -2,6 +2,7 @@ using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using PLATEAU.Dataset; +using PLATEAU.Geometries; using PLATEAU.Network; namespace PLATEAU.Test.Dataset @@ -35,7 +36,28 @@ public void TestMeshCode() Assert.AreEqual("53392642", info.GridCode.ToString()); info.Dispose(); } - + + [TestMethod] + public void TestEpsgCode() + { + string path = "data/udx/bldg/53392642_bldg_6697_op2.gml"; + var info = GmlFile.Create(path); + Assert.AreEqual(6697, info.Epsg); + Assert.IsTrue(CoordinateReferenceFactory.IsPolarCoordinateSystem(info.Epsg)); + info.Dispose(); + } + + + [TestMethod] + public void TestEpsgCodePlane() + { + string path = "data/udx/unf/08EE763_unf_10169_sewer_op.gml"; + var info = GmlFile.Create(path); + Assert.AreEqual(10169, info.Epsg); + Assert.IsFalse(CoordinateReferenceFactory.IsPolarCoordinateSystem(info.Epsg)); + info.Dispose(); + } + [TestMethod] public void DirNameToPackage_Returns_Gml_Package() { diff --git a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Geom/GeoReferenceTests.cs b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Geom/GeoReferenceTests.cs index 8e44df04..61879715 100644 --- a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Geom/GeoReferenceTests.cs +++ b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Geom/GeoReferenceTests.cs @@ -121,5 +121,16 @@ private static void CheckProjectUnproject(PlateauVector3d referencePoint, float Assert.IsTrue(Math.Abs(lat.Latitude - latitude) < 0.00000001);//およそ1mm相当の誤差以内か Assert.IsTrue(Math.Abs(lat.Longitude - longitude) < 0.00000001);//およそ1mm相当の誤差以内か } + + [TestMethod] + public void Convert_returns_same_values() + { + using var geoReference = GeoReference.Create( + new PlateauVector3d(0, 0, 0), 1.0f, CoordinateSystem.EUN, 5 + ); + var xyz = new PlateauVector3d(1, 2, 3); + Assert.AreEqual(geoReference.Project(xyz), geoReference.Convert(xyz, true, 6697)); + Assert.AreEqual(geoReference.ProjectWithoutAxisConvert(xyz), geoReference.Convert(xyz, false, 6697)); + } } } diff --git a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs index 398d4a78..672e62f9 100644 --- a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs +++ b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs @@ -96,6 +96,21 @@ public GridCode GridCode } } + /// + /// GMLファイルのEPSGコードを返します。 + /// 取得失敗時のデフォルト値はEPSG:6697です。 + /// + public int Epsg + { + get + { + ThrowIfDisposed(); + var epsg = DLLUtil.GetNativeValue(Handle, + NativeMethods.plateau_gml_file_get_epsg); + return epsg; + } + } + public string[] SearchAllCodelistPathsInGml() { var nativePaths = NativeVectorString.Create(); @@ -214,7 +229,12 @@ internal static extern APIResult plateau_gml_file_get_feature_type_str( internal static extern APIResult plateau_gml_file_get_grid_code( [In] IntPtr gmlFilePtr, out IntPtr outGridCodePtr); - + + [DllImport(DLLUtil.DllName)] + internal static extern APIResult plateau_gml_file_get_epsg( + [In] IntPtr gmlFilePtr, + out int outEpsg); + [DllImport(DLLUtil.DllName, CharSet = CharSet.Ansi)] internal static extern APIResult plateau_gml_file_fetch( [In] IntPtr gmlFilePtr, diff --git a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/CoordinateReferenceFactory.cs b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/CoordinateReferenceFactory.cs new file mode 100644 index 00000000..3d2aec12 --- /dev/null +++ b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/CoordinateReferenceFactory.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.InteropServices; +using PLATEAU.Dataset; +using PLATEAU.Interop; +using PLATEAU.Native; + +namespace PLATEAU.Geometries +{ + public static class CoordinateReferenceFactory + { + + public const int DEFAULT_EPSG = 6697; + + /// + /// 平面直角座標系への変換が必要なGMLファイルかどうかを返します。 + /// 取得失敗時のデフォルト値はtrueです。 + /// + public static bool IsPolarCoordinateSystem(int Epsg) + { + var result = NativeMethods.plateau_geometry_utils_is_polar_coordinate_system(Epsg, out var isPolar); + DLLUtil.CheckDllError(result); + return isPolar; + } + + internal static class NativeMethods + { + [DllImport(DLLUtil.DllName)] + internal static extern APIResult plateau_geometry_utils_is_polar_coordinate_system( + int epsg, + [MarshalAs(UnmanagedType.U1)] out bool outBool); + } + } +} + diff --git a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/GeoReference.cs b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/GeoReference.cs index 1c54f6d2..d90bd280 100644 --- a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/GeoReference.cs +++ b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Geometries/GeoReference.cs @@ -115,6 +115,24 @@ public PlateauVector3d Project(GeoCoordinate geoCoordinate) return outXyz; } + public PlateauVector3d Project(PlateauVector3d point) + { + var result = NativeMethods.plateau_geo_reference_project_point( + Handle, out var outXyz, + point); + DLLUtil.CheckDllError(result); + return outXyz; + } + + public PlateauVector3d ProjectWithoutAxisConvert(PlateauVector3d point) + { + var result = NativeMethods.plateau_geo_reference_project_without_axis_convert( + Handle, out var outXyz, + point); + DLLUtil.CheckDllError(result); + return outXyz; + } + public GeoCoordinate Unproject(PlateauVector3d point) { var result = NativeMethods.plateau_geo_reference_unproject( @@ -124,6 +142,22 @@ public GeoCoordinate Unproject(PlateauVector3d point) return outLatLon; } + /// + /// 指定されたEPSGコードを使用して座標変換を行います。 + /// + /// 変換する座標点 + /// 軸変換を行うかどうか + /// 使用するEPSGコード。デフォルトは6697(日本測地系2011) + /// 変換された座標点 + public PlateauVector3d Convert(PlateauVector3d point, bool convertAxis, int epsg = CoordinateReferenceFactory.DEFAULT_EPSG) + { + var result = NativeMethods.plateau_geo_reference_convert( + Handle, out var outXyz, + point, convertAxis, epsg); + DLLUtil.CheckDllError(result); + return outXyz; + } + public static PlateauVector3d ConvertAxisToENU(CoordinateSystem axis, PlateauVector3d vertex) { var result = NativeMethods.plateau_geo_reference_convert_axis_to_enu(axis, vertex, out var outVertex); @@ -213,6 +247,24 @@ internal static extern APIResult plateau_geo_reference_unproject( out GeoCoordinate outLatLon, PlateauVector3d point); + [DllImport(DLLUtil.DllName)] + internal static extern APIResult plateau_geo_reference_project_point( + [In] IntPtr geoReferencePtr, + out PlateauVector3d outXyz, + PlateauVector3d point); + + [DllImport(DLLUtil.DllName)] + internal static extern APIResult plateau_geo_reference_project_without_axis_convert( + [In] IntPtr geoReferencePtr, + out PlateauVector3d outXyz, + PlateauVector3d point); + + [DllImport(DLLUtil.DllName)] + internal static extern APIResult plateau_geo_reference_convert( + [In] IntPtr geoReferencePtr, + out PlateauVector3d outXyz, + PlateauVector3d point, [MarshalAs(UnmanagedType.U1)] bool convertAxis, int epsg); + [DllImport(DLLUtil.DllName)] internal static extern APIResult plateau_geo_reference_get_reference_point( [In] IntPtr handle, diff --git a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/PolygonMesh/MeshExtractOptions.cs b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/PolygonMesh/MeshExtractOptions.cs index 796f6f97..27698523 100644 --- a/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/PolygonMesh/MeshExtractOptions.cs +++ b/wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/PolygonMesh/MeshExtractOptions.cs @@ -72,7 +72,7 @@ public static ConvertGranularity ToConvertGranularity(this MeshGranularity g) [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct MeshExtractOptions { - public MeshExtractOptions(PlateauVector3d referencePoint, CoordinateSystem meshAxes, MeshGranularity meshGranularity, uint minLOD, uint maxLOD, bool exportAppearance, int gridCountOfSide, float unitScale, int coordinateZoneID, bool excludeCityObjectOutsideExtent, bool excludePolygonsOutsideExtent, bool enableTexturePacking, uint texturePackingResolution, bool attachMapTile, int mapTileZoomLevel, string mapTileURL) + public MeshExtractOptions(PlateauVector3d referencePoint, CoordinateSystem meshAxes, MeshGranularity meshGranularity, uint minLOD, uint maxLOD, bool exportAppearance, int gridCountOfSide, float unitScale, int coordinateZoneID, bool excludeCityObjectOutsideExtent, bool excludePolygonsOutsideExtent, bool enableTexturePacking, uint texturePackingResolution, bool attachMapTile, int mapTileZoomLevel, string mapTileURL, int epsgCode) { this.ReferencePoint = referencePoint; this.MeshAxes = meshAxes; @@ -90,6 +90,7 @@ public MeshExtractOptions(PlateauVector3d referencePoint, CoordinateSystem meshA this.AttachMapTile = attachMapTile; this.MapTileZoomLevel = mapTileZoomLevel; this.mapTileURL = mapTileURL; + this.epsgCode = epsgCode; // 上で全てのメンバー変数を設定できてますが、バリデーションをするため念のためメソッドやプロパティも呼びます。 SetLODRange(minLOD, maxLOD); @@ -224,6 +225,8 @@ public string MapTileURL } } + public int epsgCode; + /// デフォルト値の設定を返します。 internal static MeshExtractOptions DefaultValue() {