@@ -15,6 +15,7 @@ namespace {
1515 */
1616 using GridIDToObjectsMap = std::map<unsigned , std::list<const citygml::CityObject*>>;
1717 using GroupGridIDToObjectsMap = std::map<std::pair<unsigned , unsigned >, std::list<const citygml::CityObject*>>;
18+ using GroupGridIDToObjectsWithPathMap = std::map<std::pair<unsigned , unsigned >, std::list<std::pair<const citygml::CityObject*, std::string>>>;
1819
1920 bool shouldSkipCityObj (const citygml::CityObject& city_obj, const MeshExtractOptions& options, const std::vector<geometry::Extent>& extents) {
2021 if (!options.exclude_city_object_outside_extent )
@@ -169,61 +170,86 @@ namespace plateau::polygonMesh {
169170 AreaMeshFactory::combine (const CityModelVector& city_models, const MeshExtractOptions& options, unsigned lod,
170171 const plateau::geometry::GeoReference& geo_reference, const std::vector<plateau::geometry::Extent>& extents) {
171172
172- const auto & gmlPath = city_models->empty () || city_models->front ().expired () ? " " : city_models->front ().lock ()->getGmlPath ();
173- std::shared_ptr <std::vector<const CityObject*>> all_primary_city_objects = std::make_shared<std::vector<const CityObject*>>();
173+ // 各CityObjectとそのソースのgmlPathをペアで保持
174+ std::shared_ptr<std::vector<std::pair<const CityObject*, std::string>>> all_primary_city_objects =
175+ std::make_shared<std::vector<std::pair<const CityObject*, std::string>>>();
174176
175177 const auto & _city_models = *city_models;
176178 for (const auto & city_model : _city_models) {
177179
178180 if (city_model.expired ()) continue ; // 参照が切れている場合はスキップ
179181
182+ const auto & gmlPath = city_model.lock ()->getGmlPath ();
180183 auto city_objects =
181184 city_model.lock ()->getAllCityObjectsOfType (PrimaryCityObjectTypes::getPrimaryTypeMask ());
182185
183- all_primary_city_objects->insert (all_primary_city_objects->end (),
184- city_objects.begin (), city_objects.end ());
186+ for (const auto & city_obj : city_objects) {
187+ all_primary_city_objects->emplace_back (city_obj, gmlPath);
188+ }
185189 }
186190
187- auto merged_meshes = GridMergeResult ();
188-
189- // メッシュ生成
190- MeshFactory mesh_factory (nullptr , options, extents, geo_reference);
191-
192- // グループ内の各主要地物のループ
191+ // LODレベルでグループ分けします。
192+ // グループIDとグリッドIDのペアをキーとし、グリッドIDは常に0(グリッド分割なし)
193+ auto group_id_to_primary_objects_map = GroupGridIDToObjectsWithPathMap ();
193194 const auto & all_primary_city_objects_in_model = *all_primary_city_objects;
194- for (const auto & primary_object : all_primary_city_objects_in_model) {
195195
196- if (options.highest_lod_only ) {
197- // highest_lod_only オプションが有効な場合、最大LODのみを対象とします。
198- unsigned max_lod_in_obj = PolygonMeshUtils::max_lod_in_specification_;
199- for (unsigned target_lod = lod + 1 ; target_lod <= PolygonMeshUtils::max_lod_in_specification_; ++target_lod) {
200- bool target_lod_exists =
201- PolygonMeshUtils::findFirstPolygon (primary_object, target_lod) != nullptr ;
202- if (!target_lod_exists) {
203- max_lod_in_obj = target_lod - 1 ;
204- break ;
205- }
196+ for (const auto & [primary_object, gmlPath] : all_primary_city_objects_in_model) {
197+ // この CityObject について、最大でどのLODまで存在するか確認します。
198+ unsigned max_lod_in_obj = PolygonMeshUtils::max_lod_in_specification_;
199+ for (unsigned target_lod = lod + 1 ; target_lod <= PolygonMeshUtils::max_lod_in_specification_; ++target_lod) {
200+ bool target_lod_exists =
201+ PolygonMeshUtils::findFirstPolygon (primary_object, target_lod) != nullptr ;
202+ if (!target_lod_exists) {
203+ max_lod_in_obj = target_lod - 1 ;
204+ break ;
206205 }
206+ }
207+
208+ if (options.highest_lod_only ) {
209+ // highest_lod_only オプションが有効な場合、最大LODのみを対象とします。
207210 if (lod != max_lod_in_obj) {
208211 // 最大LOD以外はスキップします。
209212 continue ;
210213 }
211- }
212-
213- if (MeshExtractor::isTypeToSkip (primary_object->getType ())) continue ;
214- if (MeshExtractor::shouldContainPrimaryMesh (lod, *primary_object)) {
215- mesh_factory.addPolygonsInPrimaryCityObject (*primary_object, lod, gmlPath);
216214 }
217215
218- if (lod >= 2 ) {
219- // 主要地物の子である各最小地物をメッシュに加えます。
220- auto atomic_objects = PolygonMeshUtils::getChildCityObjectsRecursive (*primary_object);
221- mesh_factory.addPolygonsInAtomicCityObjects (*primary_object, atomic_objects, lod, gmlPath);
216+ // グループに追加します。
217+ // grid_idは常に0(グリッド分割なし)
218+ unsigned grid_id = 0 ;
219+ unsigned group_id = max_lod_in_obj;
220+ const auto group_grid_id = std::make_pair (group_id, grid_id);
221+
222+ if (group_id_to_primary_objects_map.find (group_grid_id) == group_id_to_primary_objects_map.end ())
223+ group_id_to_primary_objects_map[group_grid_id] = std::list<std::pair<const CityObject*, std::string>>();
224+
225+ group_id_to_primary_objects_map.at (group_grid_id).emplace_back (primary_object, gmlPath);
226+ }
227+
228+ // グループごとにメッシュを結合します。
229+ auto merged_meshes = GridMergeResult ();
230+
231+ // グループごとのループ
232+ for (const auto & [id, primary_objects] : group_id_to_primary_objects_map) {
233+ // 1グループのメッシュ生成
234+ MeshFactory mesh_factory (nullptr , options, extents, geo_reference);
235+
236+ // グループ内の各主要地物のループ
237+ for (const auto & [primary_object, gmlPath] : primary_objects) {
238+ if (MeshExtractor::isTypeToSkip (primary_object->getType ())) continue ;
239+ if (MeshExtractor::shouldContainPrimaryMesh (lod, *primary_object)) {
240+ mesh_factory.addPolygonsInPrimaryCityObject (*primary_object, lod, gmlPath);
241+ }
242+
243+ if (lod >= 2 ) {
244+ // 主要地物の子である各最小地物をメッシュに加えます。
245+ auto atomic_objects = PolygonMeshUtils::getChildCityObjectsRecursive (*primary_object);
246+ mesh_factory.addPolygonsInAtomicCityObjects (*primary_object, atomic_objects, lod, gmlPath);
247+ }
248+ mesh_factory.incrementPrimaryIndex ();
222249 }
223- mesh_factory.incrementPrimaryIndex ();
250+ mesh_factory.optimizeMesh ();
251+ merged_meshes.emplace (id, mesh_factory.releaseMesh ());
224252 }
225- mesh_factory.optimizeMesh ();
226- merged_meshes.emplace (std::make_pair (0 ,0 ), mesh_factory.releaseMesh ());
227253
228254 return merged_meshes;
229255 }
0 commit comments