/src/gdal/ogr/ogrsf_frmts/lvbag/ogrlvbagdatasource.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: LV BAG Translator |
4 | | * Purpose: Implements OGRLVBAGDataSource. |
5 | | * Author: Laixer B.V., info at laixer dot com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2020, Laixer B.V. <info at laixer dot com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #include "ogr_lvbag.h" |
14 | | #include "ogrsf_frmts.h" |
15 | | #include "ogrunionlayer.h" |
16 | | #include "ogrlayerpool.h" |
17 | | |
18 | | #include <algorithm> |
19 | | |
20 | | /************************************************************************/ |
21 | | /* OGRLVBAGDataSource() */ |
22 | | /************************************************************************/ |
23 | | |
24 | | OGRLVBAGDataSource::OGRLVBAGDataSource() |
25 | 24.3k | : poPool{new OGRLayerPool{}}, papoLayers{OGRLVBAG::LayerVector{}} |
26 | 24.3k | { |
27 | 24.3k | const int nMaxSimultaneouslyOpened = |
28 | 24.3k | std::max(atoi(CPLGetConfigOption("OGR_LVBAG_MAX_OPENED", "100")), 1); |
29 | 24.3k | if (poPool->GetMaxSimultaneouslyOpened() != nMaxSimultaneouslyOpened) |
30 | 0 | { |
31 | 0 | poPool.reset(new OGRLayerPool(nMaxSimultaneouslyOpened)); |
32 | 0 | } |
33 | 24.3k | } |
34 | | |
35 | | /************************************************************************/ |
36 | | /* Open() */ |
37 | | /************************************************************************/ |
38 | | |
39 | | int OGRLVBAGDataSource::Open(const char *pszFilename, char **papszOpenOptionsIn) |
40 | 18.8k | { |
41 | 18.8k | auto poLayer = std::unique_ptr<OGRLVBAGLayer>{ |
42 | 18.8k | new OGRLVBAGLayer{pszFilename, poPool.get(), papszOpenOptionsIn}}; |
43 | 18.8k | if (poLayer && !poLayer->TouchLayer()) |
44 | 0 | { |
45 | 0 | return FALSE; |
46 | 0 | } |
47 | | |
48 | 18.8k | papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW, std::move(poLayer)}); |
49 | | |
50 | 18.8k | if ((static_cast<int>(papoLayers.size()) + 1) % |
51 | 18.8k | poPool->GetMaxSimultaneouslyOpened() == |
52 | 18.8k | 0 && |
53 | 0 | poPool->GetSize() > 0) |
54 | 0 | { |
55 | 0 | TryCoalesceLayers(); |
56 | 0 | } |
57 | | |
58 | 18.8k | return TRUE; |
59 | 18.8k | } |
60 | | |
61 | | /************************************************************************/ |
62 | | /* TryCoalesceLayers() */ |
63 | | /************************************************************************/ |
64 | | |
65 | | void OGRLVBAGDataSource::TryCoalesceLayers() |
66 | 43.2k | { |
67 | 43.2k | std::vector<int> paGroup = {}; |
68 | 43.2k | std::map<int, std::vector<int>> paMergeVector = {}; |
69 | | |
70 | | // FUTURE: This can be optimized |
71 | | // Find similar layers by doing a triangular matrix |
72 | | // comparison across all layers currently enlisted. |
73 | 80.8k | for (size_t i = 0; i < papoLayers.size(); ++i) |
74 | 37.6k | { |
75 | 37.6k | std::vector<int> paVector = {}; |
76 | 75.2k | for (size_t j = 0; j < papoLayers.size(); ++j) |
77 | 37.6k | { |
78 | 37.6k | if (std::find(paGroup.cbegin(), paGroup.cend(), |
79 | 37.6k | static_cast<int>(j)) != paGroup.cend()) |
80 | 0 | { |
81 | 0 | continue; |
82 | 0 | } |
83 | | |
84 | 37.6k | OGRLayer *poLayerLHS = papoLayers[i].second.get(); |
85 | 37.6k | OGRLayer *poLayerRHS = papoLayers[j].second.get(); |
86 | | |
87 | 37.6k | if (j > i && EQUAL(poLayerLHS->GetName(), poLayerRHS->GetName())) |
88 | 0 | { |
89 | 0 | if (poLayerLHS->GetGeomType() == poLayerRHS->GetGeomType() && |
90 | 0 | poLayerLHS->GetLayerDefn()->IsSame( |
91 | 0 | poLayerRHS->GetLayerDefn())) |
92 | 0 | { |
93 | 0 | paVector.push_back(static_cast<int>(j)); |
94 | 0 | paGroup.push_back(static_cast<int>(j)); |
95 | 0 | } |
96 | 0 | } |
97 | 37.6k | } |
98 | 37.6k | if (!paVector.empty()) |
99 | 0 | { |
100 | 0 | paMergeVector.insert({static_cast<int>(i), paVector}); |
101 | 0 | } |
102 | 37.6k | } |
103 | | |
104 | 43.2k | if (paMergeVector.empty()) |
105 | 43.2k | { |
106 | 43.2k | return; |
107 | 43.2k | } |
108 | | |
109 | 0 | for (const auto &mergeLayer : paMergeVector) |
110 | 0 | { |
111 | 0 | const int baseLayerIdx = mergeLayer.first; |
112 | 0 | const std::vector<int> papoLayersIdx = mergeLayer.second; |
113 | |
|
114 | 0 | int nSrcLayers = static_cast<int>(papoLayersIdx.size()) + 1; |
115 | 0 | OGRLayer **papoSrcLayers = static_cast<OGRLayer **>( |
116 | 0 | CPLRealloc(nullptr, sizeof(OGRLayer *) * nSrcLayers)); |
117 | |
|
118 | 0 | CPLAssert(papoLayers[baseLayerIdx].second); |
119 | |
|
120 | 0 | int idx = 0; |
121 | 0 | papoSrcLayers[idx++] = papoLayers[baseLayerIdx].second.release(); |
122 | 0 | for (const auto &poLayerIdx : papoLayersIdx) |
123 | 0 | { |
124 | 0 | papoSrcLayers[idx++] = papoLayers[poLayerIdx].second.release(); |
125 | 0 | } |
126 | |
|
127 | 0 | OGRLayer *poBaseLayer = papoSrcLayers[0]; |
128 | |
|
129 | 0 | auto poLayer = std::make_unique<OGRUnionLayer>( |
130 | 0 | poBaseLayer->GetName(), nSrcLayers, papoSrcLayers, TRUE); |
131 | |
|
132 | 0 | OGRFeatureDefn *poBaseLayerDefn = poBaseLayer->GetLayerDefn(); |
133 | |
|
134 | 0 | poLayer->SetFields(FIELD_FROM_FIRST_LAYER, poBaseLayerDefn); |
135 | |
|
136 | 0 | papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW, |
137 | 0 | OGRLayerUniquePtr{poLayer.release()}}); |
138 | 0 | } |
139 | | |
140 | | // Erase all released pointers |
141 | 0 | auto it = papoLayers.begin(); |
142 | 0 | while (it != papoLayers.end()) |
143 | 0 | { |
144 | 0 | if (!it->second) |
145 | 0 | { |
146 | 0 | it = papoLayers.erase(it); |
147 | 0 | } |
148 | 0 | else |
149 | 0 | { |
150 | 0 | ++it; |
151 | 0 | } |
152 | 0 | } |
153 | 0 | } |
154 | | |
155 | | /************************************************************************/ |
156 | | /* GetLayer() */ |
157 | | /************************************************************************/ |
158 | | |
159 | | const OGRLayer *OGRLVBAGDataSource::GetLayer(int iLayer) const |
160 | 18.8k | { |
161 | 18.8k | if (iLayer < 0 || iLayer >= GetLayerCount()) |
162 | 0 | { |
163 | 0 | return nullptr; |
164 | 0 | } |
165 | 18.8k | return papoLayers[iLayer].second.get(); |
166 | 18.8k | } |
167 | | |
168 | | /************************************************************************/ |
169 | | /* GetLayerCount() */ |
170 | | /************************************************************************/ |
171 | | |
172 | | int OGRLVBAGDataSource::GetLayerCount() const |
173 | 43.2k | { |
174 | 43.2k | const_cast<OGRLVBAGDataSource *>(this)->TryCoalesceLayers(); |
175 | 43.2k | return static_cast<int>(papoLayers.size()); |
176 | 43.2k | } |
177 | | |
178 | | /************************************************************************/ |
179 | | /* TestCapability() */ |
180 | | /************************************************************************/ |
181 | | |
182 | | int OGRLVBAGDataSource::TestCapability(const char * /* pszCap */) const |
183 | 0 | { |
184 | 0 | return FALSE; |
185 | 0 | } |