Line data Source code
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 670 : OGRLVBAGDataSource::OGRLVBAGDataSource() 25 670 : : poPool{new OGRLayerPool{}}, papoLayers{OGRLVBAG::LayerVector{}} 26 : { 27 : const int nMaxSimultaneouslyOpened = 28 670 : std::max(atoi(CPLGetConfigOption("OGR_LVBAG_MAX_OPENED", "100")), 1); 29 670 : if (poPool->GetMaxSimultaneouslyOpened() != nMaxSimultaneouslyOpened) 30 : { 31 0 : poPool.reset(new OGRLayerPool(nMaxSimultaneouslyOpened)); 32 : } 33 670 : } 34 : 35 : /************************************************************************/ 36 : /* Open() */ 37 : /************************************************************************/ 38 : 39 29 : int OGRLVBAGDataSource::Open(const char *pszFilename, char **papszOpenOptionsIn) 40 : { 41 : auto poLayer = std::unique_ptr<OGRLVBAGLayer>{ 42 58 : new OGRLVBAGLayer{pszFilename, poPool.get(), papszOpenOptionsIn}}; 43 29 : if (poLayer && !poLayer->TouchLayer()) 44 : { 45 0 : return FALSE; 46 : } 47 : 48 29 : papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW, std::move(poLayer)}); 49 : 50 29 : if ((static_cast<int>(papoLayers.size()) + 1) % 51 29 : poPool->GetMaxSimultaneouslyOpened() == 52 29 : 0 && 53 0 : poPool->GetSize() > 0) 54 : { 55 0 : TryCoalesceLayers(); 56 : } 57 : 58 29 : return TRUE; 59 : } 60 : 61 : /************************************************************************/ 62 : /* TryCoalesceLayers() */ 63 : /************************************************************************/ 64 : 65 848 : void OGRLVBAGDataSource::TryCoalesceLayers() 66 : { 67 848 : std::vector<int> paGroup = {}; 68 848 : 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 1058 : for (size_t i = 0; i < papoLayers.size(); ++i) 74 : { 75 420 : std::vector<int> paVector = {}; 76 434 : for (size_t j = 0; j < papoLayers.size(); ++j) 77 : { 78 227 : if (std::find(paGroup.cbegin(), paGroup.cend(), 79 224 : static_cast<int>(j)) != paGroup.cend()) 80 : { 81 3 : continue; 82 : } 83 : 84 221 : OGRLayer *poLayerLHS = papoLayers[i].second.get(); 85 221 : OGRLayer *poLayerRHS = papoLayers[j].second.get(); 86 : 87 221 : if (j > i && EQUAL(poLayerLHS->GetName(), poLayerRHS->GetName())) 88 : { 89 4 : if (poLayerLHS->GetGeomType() == poLayerRHS->GetGeomType() && 90 4 : poLayerLHS->GetLayerDefn()->IsSame( 91 2 : poLayerRHS->GetLayerDefn())) 92 : { 93 2 : paVector.push_back(static_cast<int>(j)); 94 2 : paGroup.push_back(static_cast<int>(j)); 95 : } 96 : } 97 : } 98 210 : if (!paVector.empty()) 99 : { 100 2 : paMergeVector.insert({static_cast<int>(i), paVector}); 101 : } 102 : } 103 : 104 848 : if (paMergeVector.empty()) 105 : { 106 846 : return; 107 : } 108 : 109 4 : for (const auto &mergeLayer : paMergeVector) 110 : { 111 2 : const int baseLayerIdx = mergeLayer.first; 112 4 : const std::vector<int> papoLayersIdx = mergeLayer.second; 113 : 114 2 : int nSrcLayers = static_cast<int>(papoLayersIdx.size()) + 1; 115 : OGRLayer **papoSrcLayers = static_cast<OGRLayer **>( 116 2 : CPLRealloc(nullptr, sizeof(OGRLayer *) * nSrcLayers)); 117 : 118 2 : CPLAssert(papoLayers[baseLayerIdx].second); 119 : 120 2 : int idx = 0; 121 2 : papoSrcLayers[idx++] = papoLayers[baseLayerIdx].second.release(); 122 4 : for (const auto &poLayerIdx : papoLayersIdx) 123 : { 124 2 : papoSrcLayers[idx++] = papoLayers[poLayerIdx].second.release(); 125 : } 126 : 127 2 : OGRLayer *poBaseLayer = papoSrcLayers[0]; 128 : 129 : auto poLayer = std::make_unique<OGRUnionLayer>( 130 2 : poBaseLayer->GetName(), nSrcLayers, papoSrcLayers, TRUE); 131 : 132 2 : OGRFeatureDefn *poBaseLayerDefn = poBaseLayer->GetLayerDefn(); 133 : 134 2 : poLayer->SetFields(FIELD_FROM_FIRST_LAYER, poBaseLayerDefn); 135 : 136 2 : papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW, 137 4 : OGRLayerUniquePtr{poLayer.release()}}); 138 : } 139 : 140 : // Erase all released pointers 141 2 : auto it = papoLayers.begin(); 142 9 : while (it != papoLayers.end()) 143 : { 144 7 : if (!it->second) 145 : { 146 4 : it = papoLayers.erase(it); 147 : } 148 : else 149 : { 150 3 : ++it; 151 : } 152 : } 153 : } 154 : 155 : /************************************************************************/ 156 : /* GetLayer() */ 157 : /************************************************************************/ 158 : 159 96 : const OGRLayer *OGRLVBAGDataSource::GetLayer(int iLayer) const 160 : { 161 96 : if (iLayer < 0 || iLayer >= GetLayerCount()) 162 : { 163 7 : return nullptr; 164 : } 165 89 : return papoLayers[iLayer].second.get(); 166 : } 167 : 168 : /************************************************************************/ 169 : /* GetLayerCount() */ 170 : /************************************************************************/ 171 : 172 848 : int OGRLVBAGDataSource::GetLayerCount() const 173 : { 174 848 : const_cast<OGRLVBAGDataSource *>(this)->TryCoalesceLayers(); 175 848 : return static_cast<int>(papoLayers.size()); 176 : } 177 : 178 : /************************************************************************/ 179 : /* TestCapability() */ 180 : /************************************************************************/ 181 : 182 19 : int OGRLVBAGDataSource::TestCapability(const char * /* pszCap */) const 183 : { 184 19 : return FALSE; 185 : }