| 131 | } // namespace |
| 132 | |
| 133 | void BuildRoadAltitudes(std::string const & mwmPath, AltitudeGetter & altitudeGetter) |
| 134 | { |
| 135 | try |
| 136 | { |
| 137 | // Preparing altitude information. |
| 138 | Processor processor(altitudeGetter); |
| 139 | feature::ForEachFeature(mwmPath, processor); |
| 140 | processor.m_altitudeGetter.PrintStatsAndPurge(); |
| 141 | |
| 142 | if (!processor.HasAltitudeInfo()) |
| 143 | { |
| 144 | // Possible for small islands like Bouvet or Willis. |
| 145 | LOG(LWARNING, ("No altitude information for road features of mwm:", mwmPath)); |
| 146 | return; |
| 147 | } |
| 148 | |
| 149 | FilesContainerW cont(mwmPath, FileWriter::OP_WRITE_EXISTING); |
| 150 | auto w = cont.GetWriter(ALTITUDES_FILE_TAG); |
| 151 | |
| 152 | AltitudeHeader header; |
| 153 | header.m_minAltitude = processor.m_minAltitude; |
| 154 | |
| 155 | auto const startOffset = w->Pos(); |
| 156 | header.Serialize(*w); |
| 157 | { |
| 158 | // Altitude availability serialization. |
| 159 | coding::FreezeVisitor<Writer> visitor(*w); |
| 160 | succinct::rs_bit_vector(&processor.m_altitudeAvailabilityBuilder).map(visitor); |
| 161 | } |
| 162 | header.m_featureTableOffset = base::checked_cast<uint32_t>(w->Pos() - startOffset); |
| 163 | |
| 164 | std::vector<uint32_t> offsets; |
| 165 | std::vector<uint8_t> deltas; |
| 166 | { |
| 167 | // Altitude info serialization to memory. |
| 168 | MemWriter<std::vector<uint8_t>> writer(deltas); |
| 169 | for (auto const & a : processor.m_featureAltitudes) |
| 170 | { |
| 171 | offsets.push_back(base::checked_cast<uint32_t>(writer.Pos())); |
| 172 | a.m_altitudes.Serialize(header.m_minAltitude, writer); |
| 173 | } |
| 174 | } |
| 175 | { |
| 176 | // Altitude offsets serialization. |
| 177 | CHECK(base::IsSortedAndUnique(offsets), ()); |
| 178 | |
| 179 | succinct::elias_fano::elias_fano_builder builder(offsets.back(), offsets.size()); |
| 180 | for (uint32_t offset : offsets) |
| 181 | builder.push_back(offset); |
| 182 | |
| 183 | coding::FreezeVisitor<Writer> visitor(*w); |
| 184 | succinct::elias_fano(&builder).map(visitor); |
| 185 | } |
| 186 | // Writing altitude info. |
| 187 | header.m_altitudesOffset = base::checked_cast<uint32_t>(w->Pos() - startOffset); |
| 188 | w->Write(deltas.data(), deltas.size()); |
| 189 | w->WritePaddingByEnd(8); |
| 190 | header.m_endOffset = base::checked_cast<uint32_t>(w->Pos() - startOffset); |