Skip to content
Open
Changes from all commits
Commits
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
92 changes: 59 additions & 33 deletions src/polygon_mesh/area_mesh_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace {
*/
using GridIDToObjectsMap = std::map<unsigned, std::list<const citygml::CityObject*>>;
using GroupGridIDToObjectsMap = std::map<std::pair<unsigned, unsigned>, std::list<const citygml::CityObject*>>;
using GroupGridIDToObjectsWithPathMap = std::map<std::pair<unsigned, unsigned>, std::list<std::pair<const citygml::CityObject*, std::string>>>;

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 @@ -169,61 +170,86 @@ namespace plateau::polygonMesh {
AreaMeshFactory::combine(const 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*>>();
// 各CityObjectとそのソースのgmlPathをペアで保持
std::shared_ptr<std::vector<std::pair<const CityObject*, std::string>>> all_primary_city_objects =
std::make_shared<std::vector<std::pair<const CityObject*, std::string>>>();

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

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

const auto& gmlPath = city_model.lock()->getGmlPath();
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());
for (const auto& city_obj : city_objects) {
all_primary_city_objects->emplace_back(city_obj, gmlPath);
}
}

auto merged_meshes = GridMergeResult();

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

// グループ内の各主要地物のループ
// LODレベルでグループ分けします。
// グループIDとグリッドIDのペアをキーとし、グリッドIDは常に0(グリッド分割なし)
auto group_id_to_primary_objects_map = GroupGridIDToObjectsWithPathMap();
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;
}
for (const auto& [primary_object, gmlPath] : all_primary_city_objects_in_model) {
// この CityObject について、最大でどの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 (options.highest_lod_only) {
// highest_lod_only オプションが有効な場合、最大LODのみを対象とします。
if (lod != max_lod_in_obj) {
// 最大LOD以外はスキップします。
continue;
}
}

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);
// グループに追加します。
// grid_idは常に0(グリッド分割なし)
unsigned grid_id = 0;
unsigned group_id = max_lod_in_obj;
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<std::pair<const CityObject*, std::string>>();

group_id_to_primary_objects_map.at(group_grid_id).emplace_back(primary_object, gmlPath);
}

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

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

// グループ内の各主要地物のループ
for (const auto& [primary_object, gmlPath] : primary_objects) {
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.incrementPrimaryIndex();
mesh_factory.optimizeMesh();
merged_meshes.emplace(id, mesh_factory.releaseMesh());
}
mesh_factory.optimizeMesh();
merged_meshes.emplace(std::make_pair(0,0), mesh_factory.releaseMesh());

return merged_meshes;
}
Expand Down