Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<core:CityModel xmlns:brid="http://www.opengis.net/citygml/bridge/2.0" xmlns:wtr="http://www.opengis.net/citygml/waterbody/2.0" xmlns:tran="http://www.opengis.net/citygml/transportation/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:frn="http://www.opengis.net/citygml/cityfurniture/2.0" xmlns:veg="http://www.opengis.net/citygml/vegetation/2.0" xmlns:sch="http://www.ascc.net/xml/schematron" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:tun="http://www.opengis.net/citygml/tunnel/2.0" xmlns:tex="http://www.opengis.net/citygml/texturedsurface/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:luse="http://www.opengis.net/citygml/landuse/2.0" xmlns:uro="https://www.geospatial.jp/iur/uro/3.1" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:smil20="http://www.w3.org/2001/SMIL20/" xmlns:pbase="http://www.opengis.net/citygml/profiles/base/2.0" xmlns:smil20lang="http://www.w3.org/2001/SMIL20/Language" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0" xsi:schemaLocation="https://www.geospatial.jp/iur/urf/3.1 ../../schemas/iur/urf/3.1/urbanFunction.xsd https://www.geospatial.jp/iur/uro/3.1 ../../schemas/iur/uro/3.1/urbanObject.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/landuse/2.0 http://schemas.opengis.net/citygml/landuse/2.0/landUse.xsd http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/transportation/2.0 http://schemas.opengis.net/citygml/transportation/2.0/transportation.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/cityobjectgroup/2.0 http://schemas.opengis.net/citygml/cityobjectgroup/2.0/cityObjectGroup.xsd http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/base/gml.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd">
<gml:boundedBy>
<gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/10169" srsDimension="3">
<gml:lowerCorner>156561.10929971817 21007.437699998685 0</gml:lowerCorner>
<gml:upperCorner>157517.0072997175 22010.374800001056 225.3813</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>

<core:cityObjectMember>
<uro:Manhole gml:id="unf_f15bce0a-e6b5-41c2-a4ea-140f966686c3">
<gml:name>雨水マンホール</gml:name>
<core:creationDate>2025-03-21</core:creationDate>
<frn:lod2Geometry>
<gml:Solid srsName="http://www.opengis.net/def/crs/EPSG/0/10169" srsDimension="3">
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="poly-7a90fd2f-c13c-4824-ab37-9cc81d19ad51">
<gml:exterior>
<gml:LinearRing>
<gml:posList>157110.9434 21547.8443 136.489 157111.4651 21547.5479 136.489 157111.4651 21547.5479 135.139 157110.9434 21547.8443 135.139 157110.9434 21547.8443 136.489</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="poly-47a82d4d-d696-4dd1-b7b3-5cbe9336f141">
<gml:exterior>
<gml:LinearRing>
<gml:posList>157111.7615 21548.0695 135.139 157111.4651 21547.5479 135.139 157111.4651 21547.5479 136.489 157111.7615 21548.0695 136.489 157111.7615 21548.0695 135.139</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="poly-6f56700e-61de-439a-aefa-c04c1eb4aaeb">
<gml:exterior>
<gml:LinearRing>
<gml:posList>157111.7615 21548.0695 136.489 157111.4651 21547.5479 136.489 157110.9434 21547.8443 136.489 157111.2398 21548.366 136.489 157111.7615 21548.0695 136.489</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="poly-4f0fbdad-b948-4122-95c2-b8f2656630c3">
<gml:exterior>
<gml:LinearRing>
<gml:posList>157110.9434 21547.8443 135.139 157111.4651 21547.5479 135.139 157111.7615 21548.0695 135.139 157111.2398 21548.366 135.139 157110.9434 21547.8443 135.139</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="poly-f2f88f9b-3671-4722-a933-bd81c52b94fa">
<gml:exterior>
<gml:LinearRing>
<gml:posList>157111.2398 21548.366 135.139 157111.7615 21548.0695 135.139 157111.7615 21548.0695 136.489 157111.2398 21548.366 136.489 157111.2398 21548.366 135.139</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="poly-e378d104-8bd1-41b0-aa2f-b62e9f63cf1e">
<gml:exterior>
<gml:LinearRing>
<gml:posList>157110.9434 21547.8443 135.139 157111.2398 21548.366 135.139 157111.2398 21548.366 136.489 157110.9434 21547.8443 136.489 157110.9434 21547.8443 135.139</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</frn:lod2Geometry>
<uro:frnDataQualityAttribute>
<uro:DataQualityAttribute>
<uro:geometrySrcDescLod0 codeSpace="../../codelists/DataQualityAttribute_geometrySrcDesc.xml">500</uro:geometrySrcDescLod0>
<uro:geometrySrcDescLod1 codeSpace="../../codelists/DataQualityAttribute_geometrySrcDesc.xml">999</uro:geometrySrcDescLod1>
<uro:geometrySrcDescLod2 codeSpace="../../codelists/DataQualityAttribute_geometrySrcDesc.xml">500</uro:geometrySrcDescLod2>
<uro:geometrySrcDescLod3 codeSpace="../../codelists/DataQualityAttribute_geometrySrcDesc.xml">999</uro:geometrySrcDescLod3>
<uro:thematicSrcDesc codeSpace="../../codelists/DataQualityAttribute_thematicSrcDesc.xml">500</uro:thematicSrcDesc>
</uro:DataQualityAttribute>
</uro:frnDataQualityAttribute>
<uro:year>2008</uro:year>
</uro:Manhole>
</core:cityObjectMember>
</core:CityModel>
3 changes: 3 additions & 0 deletions include/plateau/dataset/gml_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace plateau::dataset {
const std::string& getPath() const;
void setPath(const std::string& path);
MeshCode getMeshCode() const;
double getEpsg() const;
bool isPolarCoordinateSystem() const;
const std::string& getFeatureType() const;
PredefinedCityModelPackage getPackage() const;
std::string getAppearanceDirectoryPath() const;
Expand Down Expand Up @@ -63,6 +65,7 @@ namespace plateau::dataset {
std::string path_;
std::string code_;
std::string feature_type_;
std::string epsg_;
bool is_valid_;
bool is_local_;
int max_lod_;
Expand Down
7 changes: 3 additions & 4 deletions include/plateau/geometry/geo_coordinate.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ namespace plateau::geometry {
* EPSGコードが 6697 のとき、それは
* 「日本測地系2011における経緯度座標系と東京湾平均海面を基準とする標高の複合座標参照系」
* になります。
* TODO
* EPSGコードの判別と、それによって処理を変える機能は未実装です。
* EPSGコードが 10162 ~ 10174 の場合は平面直角座標系となります。
*/
struct GeoCoordinate {
double latitude;
Expand Down Expand Up @@ -95,8 +94,8 @@ namespace plateau::geometry {

static Extent all() {
return {
GeoCoordinate(-90, -180, -9999),
GeoCoordinate(90, 180, 9999)
GeoCoordinate(-9999999, -9999999, -9999),
GeoCoordinate(9999999, 9999999, 9999)
};
}
};
Expand Down
5 changes: 3 additions & 2 deletions include/plateau/geometry/geo_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ namespace plateau::geometry {
/**
* 緯度・経度・高さで表現される座標を平面直角座標系に変換します。
* 座標軸変換を含みます。
*/
*/
TVec3d project(const GeoCoordinate& point) const;
TVec3d project(const TVec3d& lat_lon) const;
/// 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;
static TVec3d convertAxisFromENUTo(CoordinateSystem axis, const TVec3d& vertex);
static TVec3d convertAxisToENU(CoordinateSystem axis, const TVec3d& vertex);
static TVec3d convertAxisToENU(CoordinateSystem axis, const TVec3d& vertex);

GeoCoordinate unproject(const TVec3d& point) const;

Expand Down
20 changes: 20 additions & 0 deletions src/dataset/gml_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ namespace plateau::dataset {
return MeshCode(code_);
}

double GmlFile::getEpsg() const {
try {
return epsg_.empty() ? 6697 : std::stod(epsg_);
}
catch (const std::exception&) {
return 6697;
}
}

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_;
}
Expand Down Expand Up @@ -113,6 +132,7 @@ namespace plateau::dataset {
try {
code_ = filename_parts.empty() ? "" : filename_parts.at(0);
feature_type_ = filename_parts.size() <= 1 ? "" : filename_parts.at(1);
epsg_ = filename_parts.size() <= 2 ? "" : filename_parts.at(2);
is_valid_ = true;
}
catch (...) {
Expand Down
17 changes: 17 additions & 0 deletions src/geometry/geo_reference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ namespace plateau::geometry {
return converted_point;
}

TVec3d GeoReference::convert(const TVec3d& lat_lon, const bool convert_axis, const bool project) const {
//平面直角座標変換、座標軸変換をフラグに応じてスキップします。
TVec3d point = lat_lon;
// 平面直角座標系に変換
if (project)
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;
}

TVec3d GeoReference::convertAxisToENU(const TVec3d& vertex) const {
return convertAxisToENU(getCoordinateSystem(), vertex);
}
Expand Down
5 changes: 4 additions & 1 deletion src/polygon_mesh/mesh_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "plateau/polygon_mesh/mesh_merger.h"
#include "plateau/polygon_mesh/mesh_extractor.h"
#include "plateau/dataset/gml_file.h"


namespace plateau::polygonMesh {
Expand All @@ -33,6 +34,8 @@ namespace plateau::polygonMesh {
const Polygon& polygon, const std::string& gml_path,
const GeoReference& geo_reference, Mesh& out_mesh) {

const auto& gml = plateau::dataset::GmlFile(gml_path);

// マージ対象の情報を取得します。ここでの頂点は極座標です。
const auto& vertices_lat_lon = polygon.getVertices();
const auto& in_indices = polygon.getIndices();
Expand All @@ -53,7 +56,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.projectWithoutAxisConvert(lat_lon);
auto xyz = geo_reference.convert(lat_lon, false, gml.isPolarCoordinateSystem());
out_vertices.push_back(xyz);
}
assert(out_vertices.size() == vertices_lat_lon.size());
Expand Down
4 changes: 3 additions & 1 deletion src/polygon_mesh/polygon_mesh_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "plateau/polygon_mesh/mesh.h"
#include "plateau/geometry/geo_reference.h"
#include "citygml/citymodel.h"
#include <plateau/dataset/gml_file.h>

namespace plateau::polygonMesh {
using namespace citygml;
Expand Down Expand Up @@ -59,8 +60,9 @@ namespace plateau::polygonMesh {
if (!envelope.validBounds()) {
return TVec3d{0, 0, 0};
}
const auto& gml = plateau::dataset::GmlFile(city_model.getGmlPath());
auto city_center = (envelope.getLowerBound() + envelope.getUpperBound()) / 2.0;
return geometry::GeoReference(coordinate_zone_id).project(city_center);
return geometry::GeoReference(coordinate_zone_id).convert(city_center, true, gml.isPolarCoordinateSystem());
}

/**
Expand Down
4 changes: 3 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ add_executable(plateau_test
"test_texture_image_base.cpp"
"test_map_zoom_level_searcher.cpp"
"test_height_map_aligner.cpp"
"test_heightmap_mesh_generator.cpp")
"test_heightmap_mesh_generator.cpp"
"test_geo_reference.cpp"
)

add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/test_granularity_convert")

Expand Down
75 changes: 75 additions & 0 deletions test/test_geo_reference.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <gtest/gtest.h>
#include <plateau/geometry/geo_coordinate.h>
#include <plateau/geometry/geo_reference.h>
#include "../src/geometry/polar_to_plane_cartesian.cpp"

namespace plateau::geometry {
class GeoReferenceTest : public ::testing::Test {
protected:
void SetUp() override {
}
void TearDown() override {
}

// テスト設定
int zone_id = 9;
TVec3d ref_point = TVec3d(0, 0, 0);
float unit_scale = 1.0;
CoordinateSystem coordinate = CoordinateSystem::EUN;
GeoReference ref = GeoReference(zone_id, ref_point, unit_scale, coordinate);
TVec3d base_point = TVec3d(100, 100, 0);
};

TEST_F(GeoReferenceTest, ConvertAxisProject) { // NOLINT
// 平面直角座標変換・座標軸変換を行う
TVec3d converted = ref.convert(base_point, true, true);
TVec3d projected = ref.project(base_point);

// Expected
TVec3d position = base_point;
PolarToPlaneCartesian().project(position, zone_id);
TVec3 expected_point = GeoReference::convertAxisFromENUTo(coordinate, position);
expected_point = expected_point / unit_scale - ref_point;

ASSERT_EQ(expected_point, converted);
ASSERT_EQ(expected_point, projected);
}

TEST_F(GeoReferenceTest, ConvertProjectOnly) { // NOLINT
// 平面直角座標変換を行う・座標軸変換を行わない
TVec3d converted = ref.convert(base_point, false, true);
TVec3d projected = ref.projectWithoutAxisConvert(base_point);

// Expected
TVec3d position = base_point;
PolarToPlaneCartesian().project(position, zone_id);
TVec3 expected_point = position / unit_scale - GeoReference::convertAxisToENU(coordinate, ref_point);

ASSERT_EQ(expected_point, converted);
ASSERT_EQ(expected_point, projected);
}

TEST_F(GeoReferenceTest, ConvertAxisOnly) { // NOLINT
// 平面直角座標変換を行わない・座標軸変換を行う
TVec3d point = ref.convert(base_point, true, false);

// Expected
TVec3 expected_point = GeoReference::convertAxisFromENUTo(coordinate, base_point);
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);

// Expected
TVec3 expected_point = base_point / unit_scale - GeoReference::convertAxisToENU(coordinate, ref_point);

ASSERT_EQ(expected_point, point);
}

// fetch のテストは test_dataset.cpp にあります。

}
10 changes: 10 additions & 0 deletions test/test_gml_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ namespace plateau::dataset {
ASSERT_EQ(PredefinedCityModelPackage::Building, UdxSubFolder::getPackage("bldg"));
}

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());

auto info2 = GmlFile(std::string("foobar/udx/bldg/53392546_bldg_6697_2_op.gml"));
ASSERT_EQ(6697, info2.getEpsg());
ASSERT_TRUE(info2.isPolarCoordinateSystem());
}

// fetch のテストは test_dataset.cpp にあります。

}
Loading
Loading