Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
27180fe
複数GML結合機能
sevendev Jul 2, 2025
402c6f6
weak_ptrに変更(意味ないかも)
sevendev Jul 4, 2025
1bac893
結合時、最大LODのみを含める
sevendev Jul 4, 2025
26d76e9
最大LODのみGrid Merge , Group id ではなくGrid id を使う
sevendev Jul 7, 2025
b655432
city_modelのgrid分けの処理もTile extractorで行う
sevendev Jul 7, 2025
c15deec
Grid id ごとに階層化
sevendev Jul 7, 2025
69f1c86
Model/Node側のメソッドでchild node 有無判定( Mapを使わない )
sevendev Jul 8, 2025
03a811b
group / grid id を両方渡す
sevendev Jul 8, 2025
cf0dff1
Grid名変更
sevendev Jul 10, 2025
fd40c85
Grid名変更
sevendev Aug 18, 2025
70432d8
AIコメント対応
sevendev Aug 19, 2025
4db4a48
AIコメント対応
sevendev Aug 19, 2025
528a6ed
nitpickコメント対応
sevendev Aug 19, 2025
857913a
AIコメント対応
sevendev Aug 19, 2025
20735ae
AIコメント対応
sevendev Aug 19, 2025
e6fafaf
コメント変更
sevendev Aug 19, 2025
b5bc42c
AIコメント対応
sevendev Aug 19, 2025
fd86c9e
Unit Testが通らないので元の仕様にRevert
sevendev Aug 19, 2025
31a127d
コメント変更
sevendev Aug 19, 2025
cfd7877
refactor
sevendev Aug 20, 2025
1f3ff96
Added Unit Test.
sevendev Aug 20, 2025
dd4e68b
C#libでTestが通らなくなるのでudxのパス変更
sevendev Aug 20, 2025
625bfc9
nitpick対応
sevendev Aug 21, 2025
f02038d
nitpick対応
sevendev Aug 21, 2025
0c051e8
githubでwinのbuildが完了しないため.net standard 2.0にrevert
sevendev Aug 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion include/plateau/polygon_mesh/mesh_extract_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ namespace plateau::polygonMesh {
attach_map_tile(true),
map_tile_zoom_level(15),
map_tile_url("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg"),
epsg_code(plateau::geometry::CoordinateReferenceFactory::default_epsg)
epsg_code(plateau::geometry::CoordinateReferenceFactory::default_epsg),
highest_lod_only(false)
{}
Comment thread
sevendev marked this conversation as resolved.

public:
Expand Down Expand Up @@ -117,5 +118,12 @@ namespace plateau::polygonMesh {
* 平面直角座標系は、EPSGコードに応じて基準点を取得します。
*/
int epsg_code;

/**
* 最高LODのみを抽出するかどうかを指定します。
* true の場合、最高LODのポリゴンのみを抽出し、他のLODは無視します。
* false の場合、min_lod から max_lod までの範囲のポリゴンを抽出します。
*/
bool highest_lod_only;
};
}
2 changes: 2 additions & 0 deletions include/plateau/polygon_mesh/mesh_extractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,7 @@ namespace plateau::polygonMesh {
*/
static bool shouldContainPrimaryMesh(unsigned lod, const citygml::CityObject& primary_obj);
static bool isTypeToSkip(citygml::CityObject::CityObjectsType type);

static std::vector<geometry::Extent> extendExtents(const std::vector<geometry::Extent>& src_extents, float multiplier);
};
}
1 change: 1 addition & 0 deletions include/plateau/polygon_mesh/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ namespace plateau::polygonMesh {

Node& getRootNodeAt(size_t index);
const Node& getRootNodeAt(size_t index) const;
const int getRootNodeIndexByName(const std::string name) const;

/// 各ノードのペアレント、ルートを設定します。
void assignNodeHierarchy();
Expand Down
2 changes: 2 additions & 0 deletions include/plateau/polygon_mesh/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ namespace plateau::polygonMesh {
Node& getChildAt(unsigned int index);
const Node& getChildAt(unsigned int index) const;

const int getChildIndexByName(const std::string name) const;

/// Parent Node設定
void setParentNode(Node* node);
const Node& getParentNode() const; //Model.assignNodeHierarchyを呼ぶことで取得可能になります。
Expand Down
50 changes: 50 additions & 0 deletions include/plateau/polygon_mesh/tile_extractor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <plateau/polygon_mesh/mesh_extractor.h>
#include <libplateau_api.h>
#include <memory>
#include <plateau/polygon_mesh/mesh.h>
#include <plateau/geometry/geo_coordinate.h>
#include "citygml/citymodel.h"
#include "model.h"

namespace plateau::polygonMesh {

using CityModelVector = std::shared_ptr<std::vector<std::weak_ptr<const citygml::CityModel>>>;

/**
* TileExtractorは、複数のCityModelからメッシュを抽出し、指定された範囲(extents)に基づいて結合メッシュを抽出するクラスです。
*
*/
class LIBPLATEAU_EXPORT TileExtractor : public MeshExtractor {
public:

/**
* CityModelのリストを結合し範囲内のModelを取り出します。
*/
static std::shared_ptr<Model> extractWithCombine(
CityModelVector city_models, const MeshExtractOptions& options,
const std::vector<plateau::geometry::Extent>& extents);

/**
* CityModelのリストを結合し範囲内のModelを取り出します。
*/
static void extractWithCombine(Model& out_model,
CityModelVector city_models, const MeshExtractOptions& options,
const std::vector<plateau::geometry::Extent>& extents);

/**
* CityModelから範囲内のModelを取り出します。
*/
static std::shared_ptr<Model> extractWithGrid(
const citygml::CityModel& city_model, const MeshExtractOptions& options,
const std::vector<plateau::geometry::Extent>& extents);

/**
* CityModelから範囲内のModelを取り出します。
*/
static void extractWithGrid(Model& out_model,
const citygml::CityModel& city_model, const MeshExtractOptions& options,
const std::vector<plateau::geometry::Extent>& extents);
};
}
4 changes: 3 additions & 1 deletion src/c_wrapper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ add_library(c_wrapper OBJECT
"height_map_aligner_c.cpp"
"material_adjuster_by_attr.cpp"
"material_adjuster_by_type_c.cpp"
"heightmap_mesh_generator_c.cpp")
"heightmap_mesh_generator_c.cpp"
"tile_extractor_c.cpp"
)

if(NOT(IOS OR ANDROID))
# 非モバイル向け
Expand Down
49 changes: 49 additions & 0 deletions src/c_wrapper/tile_extractor_c.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "libplateau_c.h"
#include "city_model_c.h"
#include <plateau/polygon_mesh/tile_extractor.h>
#include <plateau/geometry/geo_coordinate.h>

using namespace libplateau;
using namespace plateau::polygonMesh;

extern "C"{

LIBPLATEAU_C_EXPORT APIResult LIBPLATEAU_C_API plateau_tile_extractor_extract_with_combine(
const CityModelHandle** const city_model_handles,
const int city_model_size,
const MeshExtractOptions options,
const std::vector<plateau::geometry::Extent>* extents,
Model* const out_model) {
Comment thread
sevendev marked this conversation as resolved.
Outdated
API_TRY{

CityModelVector city_models = std::make_shared<std::vector<std::weak_ptr<const citygml::CityModel>>>();
for (int i = 0; i < city_model_size; ++i) {
if (!city_model_handles[i]) {
continue; // nullptr の場合はスキップ
}
const auto & ptr = city_model_handles[i]->getCityModelPtr(); // ここで city_model_handles[i] のポインタを取得
std::weak_ptr<const citygml::CityModel> weak = ptr;
city_models->push_back(weak);
}

TileExtractor::extractWithCombine(*out_model, city_models, options, *extents);
return APIResult::Success;

}
API_CATCH;
return APIResult::ErrorUnknown;
}

LIBPLATEAU_C_EXPORT APIResult LIBPLATEAU_C_API plateau_tile_extractor_extract_with_grid(
const CityModelHandle* const city_model_handle,
const MeshExtractOptions options,
const std::vector<plateau::geometry::Extent>* extents,
Model* const out_model) {
API_TRY{
TileExtractor::extractWithGrid(*out_model, city_model_handle->getCityModel(), options, *extents);
return APIResult::Success;
}
Comment thread
sevendev marked this conversation as resolved.
Outdated
API_CATCH;
return APIResult::ErrorUnknown;
}
}
1 change: 1 addition & 0 deletions src/polygon_mesh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ target_sources(plateau PRIVATE
"city_object_list.cpp"
"map_attacher.cpp"
"transform.cpp"
"tile_extractor.cpp"
)
88 changes: 81 additions & 7 deletions src/polygon_mesh/area_mesh_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace {
* グリッド番号と、そのグリッドに属する CityObject のリストを対応付ける辞書です。
*/
using GridIDToObjectsMap = std::map<unsigned, std::list<const citygml::CityObject*>>;
using GroupIDToObjectsMap = GridIDToObjectsMap;
using GroupGridIDToObjectsMap = std::map<std::pair<unsigned, unsigned>, std::list<const citygml::CityObject*>>;

bool shouldSkipCityObj(const citygml::CityObject& city_obj, const MeshExtractOptions& options, const std::vector<geometry::Extent>& extents) {
if (!options.exclude_city_object_outside_extent)
Expand Down Expand Up @@ -104,7 +104,7 @@ namespace plateau::polygonMesh {
// 仕様上、あるオブジェクトのLOD i が存在すれば、同じオブジェクトの lod 0 to i-1 がすべて存在します。したがって、各オブジェクトは必ず上記グループのどれか1つに該当するはずです。
// そのようにグループ分けする利点は、
// 「高いLODを表示したが、低いLODにしか対応していない箇所が穴になってしまう」という状況で、穴をちょうど埋める範囲の低LODグループが存在することです。
auto group_id_to_primary_objects_map = GroupIDToObjectsMap();
auto group_id_to_primary_objects_map = GroupGridIDToObjectsMap();
for (const auto& [grid_id, primary_objects_in_grid] : grid_id_to_primary_objects_map) {
for (const auto& primary_object : primary_objects_in_grid) {
// この CityObject について、最大でどのLODまで存在するか確認します。
Expand All @@ -117,19 +117,30 @@ namespace plateau::polygonMesh {
break;
}
}

if (options.highest_lod_only) {
// highest_lod_only オプションが有効な場合、最大LODのみを対象とします。
if (lod != max_lod_in_obj) {
// 最大LOD以外はスキップします。
continue;
}
}

// グループに追加します。
unsigned group_id = grid_id * (PolygonMeshUtils::max_lod_in_specification_ + 1) + max_lod_in_obj;
if (group_id_to_primary_objects_map.find(group_id) == group_id_to_primary_objects_map.end())
group_id_to_primary_objects_map[group_id] = std::list<const CityObject*>();
const auto group_grid_id = std::make_pair(group_id, grid_id);
if (group_id_to_primary_objects_map.find(group_grid_id) == group_id_to_primary_objects_map.end())
group_id_to_primary_objects_map[group_grid_id] = std::list<const CityObject*>();

group_id_to_primary_objects_map.at(group_id).push_back(primary_object);
group_id_to_primary_objects_map.at(group_grid_id).push_back(primary_object);
}
}

// グループごとにメッシュを結合します。
auto merged_meshes = GridMergeResult();

// グループごとのループ
for (const auto& [group_id, primary_objects] : group_id_to_primary_objects_map) {
for (const auto& [id, primary_objects] : group_id_to_primary_objects_map) {
// 1グループのメッシュ生成
MeshFactory mesh_factory(nullptr, options, extents, geo_reference);

Expand All @@ -148,8 +159,71 @@ namespace plateau::polygonMesh {
mesh_factory.incrementPrimaryIndex();
}
mesh_factory.optimizeMesh();
merged_meshes.emplace(group_id, mesh_factory.releaseMesh());
merged_meshes.emplace(id, mesh_factory.releaseMesh());
}
return merged_meshes;
}

GridMergeResult
AreaMeshFactory::combine(CityModelVector city_models, const MeshExtractOptions& options, unsigned lod,
const plateau::geometry::GeoReference& geo_reference, const std::vector<plateau::geometry::Extent>& extents) {

const auto& gmlPath = city_models->empty() || city_models->front().expired() ? "" : city_models->front().lock()->getGmlPath();
std::shared_ptr <std::vector<const CityObject*>> all_primary_city_objects = std::make_shared<std::vector<const CityObject*>>();

const auto& _city_models = *city_models;
for (const auto& city_model : _city_models) {

if (city_model.expired()) continue; // 参照が切れている場合はスキップ

auto city_objects =
city_model.lock()->getAllCityObjectsOfType(PrimaryCityObjectTypes::getPrimaryTypeMask());

all_primary_city_objects->insert(all_primary_city_objects->end(),
city_objects.begin(), city_objects.end());
}

auto merged_meshes = GridMergeResult();

// メッシュ生成
MeshFactory mesh_factory(nullptr, options, extents, geo_reference);

// グループ内の各主要地物のループ
const auto& all_primary_city_objects_in_model = *all_primary_city_objects;
for (const auto& primary_object : all_primary_city_objects_in_model) {

if (options.highest_lod_only) {
// highest_lod_only オプションが有効な場合、最大LODのみを対象とします。
unsigned max_lod_in_obj = PolygonMeshUtils::max_lod_in_specification_;
for (unsigned target_lod = lod + 1; target_lod <= PolygonMeshUtils::max_lod_in_specification_; ++target_lod) {
bool target_lod_exists =
PolygonMeshUtils::findFirstPolygon(primary_object, target_lod) != nullptr;
if (!target_lod_exists) {
max_lod_in_obj = target_lod - 1;
break;
}
}
if (lod != max_lod_in_obj) {
// 最大LOD以外はスキップします。
continue;
}
}
Comment thread
sevendev marked this conversation as resolved.

if (MeshExtractor::isTypeToSkip(primary_object->getType())) continue;
if (MeshExtractor::shouldContainPrimaryMesh(lod, *primary_object)) {
mesh_factory.addPolygonsInPrimaryCityObject(*primary_object, lod, gmlPath);
}

if (lod >= 2) {
// 主要地物の子である各最小地物をメッシュに加えます。
auto atomic_objects = PolygonMeshUtils::getChildCityObjectsRecursive(*primary_object);
mesh_factory.addPolygonsInAtomicCityObjects(*primary_object, atomic_objects, lod, gmlPath);
}
mesh_factory.incrementPrimaryIndex();
}
mesh_factory.optimizeMesh();
merged_meshes.emplace(std::make_pair(0,0), mesh_factory.releaseMesh());

return merged_meshes;
}
}
11 changes: 9 additions & 2 deletions src/polygon_mesh/area_mesh_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

#include "citygml/citymodel.h"
#include "plateau/geometry/geo_reference.h"
#include <plateau/polygon_mesh/mesh_extractor.h>
#include <plateau/polygon_mesh/tile_extractor.h>
#include <plateau/polygon_mesh/mesh.h>
#include <plateau/polygon_mesh/mesh_extract_options.h>

namespace plateau::polygonMesh {
/// グループIDと、その結合後Meshのmapです。
using GridMergeResult = std::map<unsigned, std::unique_ptr<Mesh>>;
using GridMergeResult = std::map<std::pair<unsigned, unsigned>, std::unique_ptr<Mesh>>;
Comment thread
sevendev marked this conversation as resolved.

/**
* cityModel をグリッド状に分割し、各地物オブジェクトをグリッドに分類します。
Expand All @@ -24,5 +24,12 @@ namespace plateau::polygonMesh {
static GridMergeResult
gridMerge(const citygml::CityModel& city_model, const MeshExtractOptions& options, unsigned lod,
const plateau::geometry::GeoReference& geo_reference, const std::vector<plateau::geometry::Extent>& extents);

/**
* 複数のcity_model内のメッシュを結合して返します。
*/
static GridMergeResult
combine(CityModelVector city_models, const MeshExtractOptions& options, unsigned lod,
const plateau::geometry::GeoReference& geo_reference, const std::vector<plateau::geometry::Extent>& extents);
};
}
36 changes: 18 additions & 18 deletions src/polygon_mesh/mesh_extractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,6 @@ namespace {
return true;
}

/// extentsの幅と奥行きの長さを multiplier 倍にします。
std::vector<geometry::Extent> extendExtents(const std::vector<geometry::Extent>& src_extents, float multiplier) {
auto result = std::vector<geometry::Extent>();

for (const auto& src_extent : src_extents) {
const auto center = src_extent.centerPoint();
const auto prev_min = src_extent.min;
const auto prev_max = src_extent.max;
auto next_min = center + (prev_min - center) * multiplier;
auto next_max = center + (prev_max - center) * multiplier;
result.emplace_back(next_min, next_max);
}
return result;
}

void extractInner(
Model& out_model, const CityModel& city_model,
const MeshExtractOptions& options,
Expand All @@ -58,7 +43,7 @@ namespace {
const auto geo_reference = geometry::GeoReference(options.coordinate_zone_id, options.reference_point, options.unit_scale, options.mesh_axes);

// 範囲の境界上にある地物を取り逃さないように、範囲を少し広げます。
auto extents = extendExtents(extents_before_adjust, 1.2f);
auto extents = MeshExtractor::extendExtents(extents_before_adjust, 1.2f);

// rootNode として LODノード を作ります。
for (unsigned lod = options.min_lod; lod <= options.max_lod; lod++) {
Expand All @@ -74,8 +59,8 @@ namespace {
// 3D都市モデルをグループに分け、グループごとにメッシュをマージします。
auto result = AreaMeshFactory::gridMerge(city_model, options, lod, geo_reference, extents);
// グループごとのノードを追加します。
for (auto& [group_id, mesh] : result) {
auto node = Node("group" + std::to_string(group_id), std::move(mesh));
for (auto& [group_grid_id, mesh] : result) {
auto node = Node("group" + std::to_string(group_grid_id.first), std::move(mesh));
lod_node.addChildNode(std::move(node));
Comment thread
sevendev marked this conversation as resolved.
}
}
Expand Down Expand Up @@ -230,4 +215,19 @@ namespace plateau::polygonMesh {
// COT_CityObjectGroupも省きます。なぜなら、LOD4の建物でbldg以下の建物パーツと重複するのをなくしたいからです。
type == CityObject::CityObjectsType::COT_CityObjectGroup;
}

/// extentsの幅と奥行きの長さを multiplier 倍にします。
std::vector<geometry::Extent> MeshExtractor::extendExtents(const std::vector<geometry::Extent>& src_extents, float multiplier) {
auto result = std::vector<geometry::Extent>();

for (const auto& src_extent : src_extents) {
const auto center = src_extent.centerPoint();
const auto prev_min = src_extent.min;
const auto prev_max = src_extent.max;
auto next_min = center + (prev_min - center) * multiplier;
auto next_max = center + (prev_max - center) * multiplier;
result.emplace_back(next_min, next_max);
}
return result;
}
}
Loading