LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mvt - mvtutils.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 103 108 95.4 %
Date: 2025-10-25 23:36:32 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MVT Translator
       4             :  * Purpose:  Mapbox Vector Tile decoder
       5             :  * Author:   Even Rouault, Even Rouault <even dot rouault at spatialys dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "mvtutils.h"
      14             : #include "ogr_api.h"
      15             : 
      16             : /************************************************************************/
      17             : /*                        OGRMVTInitFields()                            */
      18             : /************************************************************************/
      19             : 
      20        1146 : void OGRMVTInitFields(OGRFeatureDefn *poFeatureDefn,
      21             :                       const CPLJSONObject &oFields,
      22             :                       const CPLJSONArray &oAttributesFromTileStats)
      23             : {
      24             :     {
      25        2292 :         OGRFieldDefn oFieldDefnId("mvt_id", OFTInteger64);
      26        1146 :         poFeatureDefn->AddFieldDefn(&oFieldDefnId);
      27             :     }
      28             : 
      29        1146 :     if (oFields.IsValid())
      30             :     {
      31       20004 :         for (const auto &oField : oFields.GetChildren())
      32             :         {
      33       18942 :             if (oField.GetType() == CPLJSONObject::Type::String)
      34             :             {
      35       18942 :                 if (oField.ToString() == "Number")
      36             :                 {
      37       16310 :                     OGRFieldDefn oFieldDefn(oField.GetName().c_str(), OFTReal);
      38             : 
      39      205416 :                     for (int i = 0; i < oAttributesFromTileStats.Size(); ++i)
      40             :                     {
      41      408118 :                         if (oAttributesFromTileStats[i].GetString(
      42      618975 :                                 "attribute") == oField.GetName() &&
      43      210857 :                             oAttributesFromTileStats[i].GetString("type") ==
      44             :                                 "number")
      45             :                         {
      46             :                             const auto eMinType = oAttributesFromTileStats[i]
      47       13596 :                                                       .GetObj("min")
      48        6798 :                                                       .GetType();
      49             :                             const auto eMaxType = oAttributesFromTileStats[i]
      50       13596 :                                                       .GetObj("max")
      51        6798 :                                                       .GetType();
      52        6798 :                             if (eMinType == CPLJSONObject::Type::Integer &&
      53             :                                 eMaxType == CPLJSONObject::Type::Integer)
      54             :                             {
      55        6398 :                                 oFieldDefn.SetType(OFTInteger);
      56             :                             }
      57         400 :                             else if ((eMinType ==
      58         400 :                                           CPLJSONObject::Type::Integer ||
      59           5 :                                       eMinType == CPLJSONObject::Type::Long) &&
      60             :                                      eMaxType == CPLJSONObject::Type::Long)
      61             :                             {
      62           5 :                                 oFieldDefn.SetType(OFTInteger64);
      63             :                             }
      64        6798 :                             if (oFieldDefn.GetType() != OFTReal)
      65             :                             {
      66             :                                 const auto oValues =
      67             :                                     oAttributesFromTileStats[i].GetObj(
      68       19209 :                                         "values");
      69        6403 :                                 if (oValues.GetType() ==
      70             :                                     CPLJSONObject::Type::Array)
      71             :                                 {
      72       12806 :                                     const auto oValuesArray = oValues.ToArray();
      73       31044 :                                     for (int iVal = 0;
      74       31044 :                                          iVal < oValuesArray.Size(); ++iVal)
      75             :                                     {
      76       24642 :                                         if (oValuesArray[iVal].GetType() ==
      77             :                                             CPLJSONObject::Type::Double)
      78             :                                         {
      79           1 :                                             oFieldDefn.SetType(OFTReal);
      80           1 :                                             break;
      81             :                                         }
      82             :                                     }
      83             :                                 }
      84             :                             }
      85        6798 :                             break;
      86             :                         }
      87             :                     }
      88             : 
      89        8155 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
      90             :                 }
      91       10787 :                 else if (oField.ToString() == "Integer")  // GDAL extension
      92             :                 {
      93           0 :                     OGRFieldDefn oFieldDefn(oField.GetName().c_str(),
      94           0 :                                             OFTInteger);
      95           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
      96             :                 }
      97       10787 :                 else if (oField.ToString() == "Boolean")
      98             :                 {
      99         115 :                     OGRFieldDefn oFieldDefn(oField.GetName().c_str(),
     100         230 :                                             OFTInteger);
     101         115 :                     oFieldDefn.SetSubType(OFSTBoolean);
     102         115 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     103             :                 }
     104             :                 else
     105             :                 {
     106       10672 :                     OGRFieldDefn oFieldDefn(oField.GetName().c_str(),
     107       21344 :                                             OFTString);
     108       10672 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     109             :                 }
     110             :             }
     111             :         }
     112             :     }
     113        1146 : }
     114             : 
     115             : /************************************************************************/
     116             : /*                     OGRMVTFindGeomTypeFromTileStat()                 */
     117             : /************************************************************************/
     118             : 
     119             : OGRwkbGeometryType
     120         657 : OGRMVTFindGeomTypeFromTileStat(const CPLJSONArray &oTileStatLayers,
     121             :                                const char *pszLayerName)
     122             : {
     123         657 :     OGRwkbGeometryType eGeomType = wkbUnknown;
     124         805 :     for (int i = 0; i < oTileStatLayers.Size(); i++)
     125             :     {
     126        1610 :         CPLJSONObject oId = oTileStatLayers[i].GetObj("layer");
     127         805 :         if (oId.IsValid() && oId.GetType() == CPLJSONObject::Type::String)
     128             :         {
     129         805 :             if (oId.ToString() == pszLayerName)
     130             :             {
     131        1971 :                 CPLJSONObject oGeom = oTileStatLayers[i].GetObj("geometry");
     132        1314 :                 if (oGeom.IsValid() &&
     133         657 :                     oGeom.GetType() == CPLJSONObject::Type::String)
     134             :                 {
     135        1971 :                     const std::string oGeomType(oGeom.ToString());
     136             :                     // Note: this information is not
     137             :                     // reliable in case
     138             :                     // of mix of geometry types
     139         657 :                     if (oGeomType == "Point")
     140             :                     {
     141         118 :                         eGeomType = wkbMultiPoint;
     142             :                     }
     143         539 :                     else if (oGeomType == "LineString")
     144             :                     {
     145          28 :                         eGeomType = wkbMultiLineString;
     146             :                     }
     147         511 :                     else if (oGeomType == "Polygon")
     148             :                     {
     149         511 :                         eGeomType = wkbMultiPolygon;
     150             :                     }
     151             :                 }
     152         657 :                 break;
     153             :             }
     154             :         }
     155             :     }
     156         657 :     return eGeomType;
     157             : }
     158             : 
     159             : /************************************************************************/
     160             : /*                     OGRMVTFindAttributesFromTileStat()               */
     161             : /************************************************************************/
     162             : 
     163             : CPLJSONArray
     164        1145 : OGRMVTFindAttributesFromTileStat(const CPLJSONArray &oTileStatLayers,
     165             :                                  const char *pszLayerName)
     166             : {
     167        1293 :     for (int i = 0; i < oTileStatLayers.Size(); i++)
     168             :     {
     169        1610 :         CPLJSONObject oId = oTileStatLayers[i].GetObj("layer");
     170         805 :         if (oId.IsValid() && oId.GetType() == CPLJSONObject::Type::String)
     171             :         {
     172         805 :             if (oId.ToString() == pszLayerName)
     173             :             {
     174             :                 CPLJSONObject oAttributes =
     175        1314 :                     oTileStatLayers[i].GetObj("attributes");
     176        1314 :                 if (oAttributes.IsValid() &&
     177         657 :                     oAttributes.GetType() == CPLJSONObject::Type::Array)
     178             :                 {
     179         657 :                     return oAttributes.ToArray();
     180             :                 }
     181           0 :                 break;
     182             :             }
     183             :         }
     184             :     }
     185         976 :     CPLJSONArray oAttributes;
     186         488 :     oAttributes.Deinit();
     187         488 :     return oAttributes;
     188             : }
     189             : 
     190             : /************************************************************************/
     191             : /*                     OGRMVTCreateFeatureFrom()                        */
     192             : /************************************************************************/
     193             : 
     194        1998 : OGRFeature *OGRMVTCreateFeatureFrom(OGRFeature *poSrcFeature,
     195             :                                     OGRFeatureDefn *poTargetFeatureDefn,
     196             :                                     bool bJsonField,
     197             :                                     const OGRSpatialReference *poSRS)
     198             : {
     199        1998 :     OGRFeature *poFeature = new OGRFeature(poTargetFeatureDefn);
     200        1998 :     if (bJsonField)
     201             :     {
     202           8 :         CPLJSONObject oProperties;
     203           4 :         bool bEmpty = true;
     204          38 :         for (int i = 1; i < poSrcFeature->GetFieldCount(); i++)
     205             :         {
     206          34 :             if (poSrcFeature->IsFieldSet(i))
     207             :             {
     208          34 :                 bEmpty = false;
     209          34 :                 const OGRFieldDefn *poFDefn = poSrcFeature->GetFieldDefnRef(i);
     210          34 :                 if (poSrcFeature->IsFieldNull(i))
     211             :                 {
     212           0 :                     oProperties.AddNull(poFDefn->GetNameRef());
     213             :                 }
     214          52 :                 else if (poFDefn->GetType() == OFTInteger ||
     215          18 :                          poFDefn->GetType() == OFTInteger64)
     216             :                 {
     217          23 :                     if (poFDefn->GetSubType() == OFSTBoolean)
     218             :                     {
     219           6 :                         oProperties.Add(poFDefn->GetNameRef(),
     220           6 :                                         poSrcFeature->GetFieldAsInteger(i) ==
     221             :                                             1);
     222             :                     }
     223             :                     else
     224             :                     {
     225          17 :                         oProperties.Add(poFDefn->GetNameRef(),
     226             :                                         poSrcFeature->GetFieldAsInteger64(i));
     227             :                     }
     228             :                 }
     229          11 :                 else if (poFDefn->GetType() == OFTReal)
     230             :                 {
     231           7 :                     oProperties.Add(poFDefn->GetNameRef(),
     232             :                                     poSrcFeature->GetFieldAsDouble(i));
     233             :                 }
     234             :                 else
     235             :                 {
     236           4 :                     oProperties.Add(poFDefn->GetNameRef(),
     237             :                                     poSrcFeature->GetFieldAsString(i));
     238             :                 }
     239             :             }
     240             :         }
     241           4 :         if (!bEmpty)
     242             :         {
     243           4 :             poFeature->SetField(
     244           8 :                 "json", oProperties.Format(CPLJSONObject::PrettyFormat::Pretty)
     245             :                             .c_str());
     246             :         }
     247             : 
     248           4 :         OGRGeometry *poSrcGeom = poSrcFeature->GetGeometryRef();
     249           4 :         if (poSrcGeom)
     250             :         {
     251           4 :             poFeature->SetGeometry(poSrcGeom);
     252             :         }
     253             : #ifdef nodef
     254             :         CPLJSONObject oObj;
     255             :         oObj.Add("type", "Feature");
     256             :         if (poSrcFeature->IsFieldSet(0))
     257             :             oObj.Add("id", poSrcFeature->GetFieldAsInteger64("mvt_id"));
     258             :         oObj.Add("properties", oProperties);
     259             :         if (poSrcGeom)
     260             :         {
     261             :             char *pszGeomJson =
     262             :                 OGR_G_ExportToJson(OGRGeometry::ToHandle(poSrcGeom));
     263             :             CPLJSONDocument oJSonDoc;
     264             :             oJSonDoc.LoadMemory(reinterpret_cast<const GByte *>(pszGeomJson));
     265             :             CPLFree(pszGeomJson);
     266             :             oObj.Add("geometry", oJSonDoc.GetRoot());
     267             :         }
     268             :         poFeature->SetNativeData(
     269             :             oObj.Format(CPLJSONObject::PrettyFormat::Pretty).c_str());
     270             :         poFeature->SetNativeMediaType("application/vnd.geo+json");
     271             : #endif
     272             :     }
     273             :     else
     274             :     {
     275        1994 :         poFeature->SetFrom(poSrcFeature);
     276             :     }
     277        1998 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     278        1998 :     if (poGeom)
     279        1998 :         poGeom->assignSpatialReference(poSRS);
     280        1998 :     return poFeature;
     281             : }

Generated by: LCOV version 1.14