
#include "MapParser.h"

#include "FileSys.h"
#include "LogicEvaluator.h"
#include "Utils.h"
#include "ajson.hpp"
#include "shapefil.h"

//地图文件名称配置
const char *c_cJunction_dbf = "Junction.dbf";
const char *c_cJunction_shp = "Junction.shp";
const char *c_cRoad_EdgeNode_dbf = "Road_EdgeNode.dbf";
const char *c_cRoad_EdgeNode_shp = "Road_EdgeNode.shp";
const char *c_cRoad_EdgeLink_dbf = "Road_EdgeLink.dbf";
const char *c_cRoad_EdgeLink_shp = "Road_EdgeLink.shp";
const char *c_cRoad_dbf = "Road.dbf";
const char *c_cRoad_shp = "Road.shp";
const char *c_cRoad_CrossArea_dbf = "Road_CrossArea.dbf";
const char *c_cRoad_CrossArea_shp = "Road_CrossArea.shp";

const char *c_cHD_LaneNode_dbf = "HD_LaneNode.dbf";
const char *c_cHD_LaneNode_shp = "HD_LaneNode.shp";
const char *c_cHD_LaneLink_dbf = "HD_LaneLink.dbf";
const char *c_cHD_LaneLink_shp = "HD_LaneLink.shp";

const char *c_cHD_EdgeNode_dbf = "HD_EdgeNode.dbf";
const char *c_cHD_EdgeNode_shp = "HD_EdgeNode.shp";
const char *c_cHD_LaneMark_dbf = "HD_LaneMark.dbf";
const char *c_cHD_LaneMark_shp = "HD_LaneMark.shp";
const char *c_cHD_EdgeLink_dbf = "HD_EdgeLink.dbf";
const char *c_cHD_EdgeLink_shp = "HD_EdgeLink.shp";

const char *c_cOBJ_TrafficSign_dbf = "OBJ_TrafficSign.dbf";
const char *c_cOBJ_TrafficSign_shp = "OBJ_TrafficSign.shp";
const char *c_cOBJ_TrafficLight_dbf = "OBJ_TrafficLight.dbf";
const char *c_cOBJ_TrafficLight_shp = "OBJ_TrafficLight.shp";

const char *c_cOBJ_Pole_dbf = "OBJ_Pole.dbf";
const char *c_cOBJ_Pole_shp = "OBJ_Pole.shp";

const char *c_cOBJ_Arrow_dbf = "OBJ_Arrow.dbf";
const char *c_cOBJ_Arrow_shp = "OBJ_Arrow.shp";
const char *c_cOBJ_Text_dbf = "OBJ_Text.dbf";
const char *c_cOBJ_Text_shp = "OBJ_Text.shp";
const char *c_cOBJ_Symbol_dbf = "OBJ_Symbol.dbf";
const char *c_cOBJ_Symbol_shp = "OBJ_Symbol.shp";
const char *c_cOBJ_StopLine_dbf = "OBJ_StopLine.dbf";
const char *c_cOBJ_StopLine_shp = "OBJ_StopLine.shp";
const char *c_cOBJ_Crossing_dbf = "OBJ_Crossing.dbf";
const char *c_cOBJ_Crossing_shp = "OBJ_Crossing.shp";
const char *c_cOBJ_OverHead_dbf = "OBJ_OverHead.dbf";
const char *c_cOBJ_OverHead_shp = "OBJ_OverHead.shp";

const char *c_cOBJ_NoParking_dbf = "OBJ_NoParking.dbf";
const char *c_cOBJ_NoParking_shp = "OBJ_NoParking.shp";

const char *c_cOBJ_SpeedBump_dbf = "OBJ_SpeedBump.dbf";
const char *c_cOBJ_SpeedBump_shp = "OBJ_SpeedBump.shp";

const char *c_cOBJ_Parking_dbf = "OBJ_Parking.dbf";
const char *c_cOBJ_Parking_shp = "OBJ_Parking.shp";

const char *c_cOBJ_FillArea_dbf = "OBJ_FillArea.dbf";
const char *c_cOBJ_FillArea_shp = "OBJ_FillArea.shp";

const char *c_cOBJ_Hydrant_dbf = "OBJ_Hydrant.dbf";
const char *c_cOBJ_Hydrant_shp = "OBJ_Hydrant.shp";

const char *c_cOBJ_BusStop_dbf = "OBJ_BusStop.dbf";
const char *c_cOBJ_BusStop_shp = "OBJ_BusStop.shp";

const char *c_cLaneADAS_csv = "LaneADAS.csv";

const char *c_cIndFacility_dbf = "IndFacility.dbf";
const char *c_cIndFacility_shp = "IndFacility.shp";
const char *c_cSpeed_dbf = "Speed.dbf";
const char *c_cFeature_json = "Feature.json";
// const char *c_cSpeed_shp = "Road.shp";

namespace jf {

HdJson MapParser::ParseAll(const std::string &strPath, MapIdNode &mapIdNode, MapIdWay &mapIdWay, ShpBound &stBound) {
    // jf_log_info("[MapParser::Parse] file : {}", strPath);

    std::map<JfDataId, HdLink> mapIdHdLink = {};

    std::map<JfDataId, std::vector<ObjTrafficLight>> mapLinkIdVctTrafficLight = {};
    std::map<JfDataId, std::vector<ObjTrafficLight>> mapLaneIdVctTrafficLight = {};

    ParseOBJTrafficLight(strPath, mapLinkIdVctTrafficLight, mapLaneIdVctTrafficLight);

    {
        std::map<JfDataId, std::vector<ObjPole>> mapLinkIdVctPole = {};
        std::map<JfDataId, std::vector<ObjStopLine>> mapLinkIdVctStopLine = {};
        std::map<JfDataId, std::vector<ObjCrossing>> mapLinkIdVctCrossing = {};
        std::map<JfDataId, std::vector<ObjPoint>> mapLinkIdVctPoint = {};
        std::map<JfDataId, std::vector<ObjTrafficSign>> mapLinkIdVctTrafficSign = {};
        std::map<JfDataId, std::vector<ObjOverHead>> mapLinkIdVctOverHead = {};
        std::map<JfDataId, std::vector<ObjFillArea>> mapLinkIdVctFillArea = {};
        std::map<JfDataId, std::vector<ObjBusStop>> mapLinkIdVctBusStop = {};
        std::map<JfDataId, std::vector<ObjHydrant>> mapLinkIdVctHydrant = {};
        std::map<JfDataId, std::vector<ObjParking>> mapLinkIdVctParking = {};
        std::map<JfDataId, std::vector<ObjSpeedBump>> mapLinkIdVctSpeedBump = {};
        std::map<JfDataId, std::vector<ObjNoParking>> mapLinkIdVctNoParking = {};

        ParseOBJTrafficSign(strPath, mapLinkIdVctTrafficSign);
        ParseOBJStopLine(strPath, mapLinkIdVctStopLine);
        ParseOBJCrossing(strPath, mapLinkIdVctCrossing);
        // ParseOBJPoint(strPath, mapLinkIdVctPoint);
        ParseOBJOverHead(strPath, mapLinkIdVctOverHead);
        ParseOBJFillArea(strPath, mapLinkIdVctFillArea);
        ParseOBJNoParking(strPath, mapLinkIdVctNoParking);
        ParseOBJSpeedBump(strPath, mapLinkIdVctSpeedBump);
        ParseOBJParking(strPath, mapLinkIdVctParking);
        ParseOBJHydrant(strPath, mapLinkIdVctHydrant);
        ParseOBJBusStop(strPath, mapLinkIdVctBusStop);
        ParseOBJPole(strPath, mapLinkIdVctPole);

        std::map<JfDataId, std::vector<RoadCrossArea>> mapLinkIdVctCrossArea = {};
        std::map<JfDataId, RoadJunction> mapLinkIdRoadJunction = {};
        std::map<JfDataId, RoadEdgeNode> mapLinkIdREdgeNode = {};
        std::map<JfDataId, RoadEdge> mapLinkIdRoadEdge = {};
        ParseRoadCrossArea(strPath, mapLinkIdVctCrossArea);
        ParseJunction(strPath, mapLinkIdRoadJunction);
        ParseRoadEdgeNode(strPath, mapLinkIdREdgeNode);
        ParseRoadEdgeLink(strPath, mapLinkIdREdgeNode, mapLinkIdRoadEdge);
        ParseRoad(strPath, mapLinkIdVctPole, mapLinkIdVctStopLine, mapLinkIdVctCrossing, mapLinkIdVctTrafficLight, mapLinkIdVctTrafficSign, mapLinkIdVctOverHead, mapLinkIdVctFillArea, mapLinkIdVctBusStop, mapLinkIdVctHydrant, mapLinkIdVctParking,
                  mapLinkIdVctSpeedBump, mapLinkIdVctNoParking, mapLinkIdVctCrossArea, mapLinkIdVctPoint, mapLinkIdRoadJunction, mapLinkIdRoadEdge, mapIdHdLink, stBound);
    }

    {
        std::map<JfDataId, HdEdgeNode> mapIdEdgeNode = {};
        std::map<JfDataId, std::vector<HdLaneMark>> mapEdgeIdVctLaneMark = {};
        std::map<JfDataId, HdEdge> mapIdEdge = {};
        ParseHDEdgeNode(strPath, mapIdEdgeNode);
        ParseHDLaneMark(strPath, mapEdgeIdVctLaneMark);
        ParseHDEdgeLink(strPath, mapIdEdgeNode, mapEdgeIdVctLaneMark, mapIdEdge, mapIdHdLink);
    }

    {
        std::map<JfDataId, HdLaneNode> mapIdLaneNode = {};
        std::map<JfDataId, std::vector<HdLaneAdas>> mapLaneIdVctLaneADASes = {};
        std::map<JfDataId, std::vector<ObjArrow>> mapLaneIdVctObjArrow = {};
        std::map<JfDataId, std::vector<ObjText>> mapLaneIdVctObjText = {};
        std::map<JfDataId, std::vector<ObjSymbol>> mapLaneIdVctObjSymbol = {};

        ParseHDLaneNode(strPath, mapIdLaneNode);
        ParseLaneADAS(strPath, mapLaneIdVctLaneADASes);
        ParseOBJArrow(strPath, mapLaneIdVctObjArrow);
        ParseOBJText(strPath, mapLaneIdVctObjText);
        ParseOBJSymbol(strPath, mapLaneIdVctObjSymbol);
        ParseHDLaneLink(strPath, mapIdLaneNode, mapLaneIdVctLaneADASes, mapLaneIdVctObjArrow, mapLaneIdVctTrafficLight, mapLaneIdVctObjText, mapLaneIdVctObjSymbol, mapIdHdLink);
    }

    HdJson result = {};
    MakeSdData(mapIdHdLink, mapIdNode, mapIdWay);
    MakeHdLink(mapIdHdLink, result);

    // insertFeatures(strPath, result);

    return result;
}

/**
 * 停止线预处理
 * @param strPath   文件路径
 * @param mapOutLinkIdVctStopLine
 */
void MapParser::ParseOBJStopLine(const std::string &strPath, std::map<JfDataId, std::vector<ObjStopLine>> &mapOutLinkIdVctStopLine) {
    std::string strFile_dbf = strPath + c_cOBJ_StopLine_dbf;
    std::string strFile_shp = strPath + c_cOBJ_StopLine_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJStopLine(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJStopLine(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_SL_type = "SL_type";
    const std::string c_strFieldName_Color = "Color";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_SL_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_SL_type.c_str());
    int nFieldIndex_Color = DBFGetFieldIndex(dbhHandle, c_strFieldName_Color.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        ObjStopLine slStopLine = {};
        slStopLine.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        slStopLine.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_SL_type);
        slStopLine.nColor = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Color);

        // nParts must be 1
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                slStopLine.vctvdGeoLink.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLinkIdVctStopLine[lRoadID].push_back(slStopLine);
        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

/**
 * 人行横道预处理
 * @param strPath
 * @param mapOutLinkIdVctCrossing
 */
void MapParser::ParseOBJCrossing(const std::string &strPath, std::map<JfDataId, std::vector<ObjCrossing>> &mapOutLinkIdVctCrossing) {
    std::string strFile_dbf = strPath + c_cOBJ_Crossing_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Crossing_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJCrossing(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJCrossing(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        ObjCrossing crCrossing = {};
        crCrossing.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));

        // nParts must be 1
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                crCrossing.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLinkIdVctCrossing[lRoadID].push_back(crCrossing);
        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

bool TRIdLess(const ObjTrafficLight objTrafficLight, const ObjTrafficLight objTrafficLight1) { return objTrafficLight.lId < objTrafficLight1.lId; }

bool TRIdEqual(const ObjTrafficLight objTrafficLight, const ObjTrafficLight objTrafficLight1) { return objTrafficLight.lId == objTrafficLight1.lId; }

/**
 * 交通信号灯预处理
 * @param strPath
 * @param mapOutLinkIdVctTrafficLight
 */
void MapParser::ParseOBJTrafficLight(const std::string &strPath, std::map<JfDataId, std::vector<ObjTrafficLight>> &mapOutLinkIdVctTrafficLight, std::map<JfDataId, std::vector<ObjTrafficLight>> &mapOutLaneIdVctTrafficLight) {
    std::string strFile_dbf = strPath + c_cOBJ_TrafficLight_dbf;
    std::string strFile_shp = strPath + c_cOBJ_TrafficLight_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";
    const std::string c_strFieldName_Heading = "Heading";
    const std::string c_strFieldName_Light_type = "Light_type";
    const std::string c_strFieldName_Light_dir = "Light_dir";
    const std::string c_strFieldName_LightArray = "LightArray";
    const std::string c_strFieldName_LightCount = "LightCount";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());
    int nFieldIndex_Heading = DBFGetFieldIndex(dbhHandle, c_strFieldName_Heading.c_str());
    int nFieldIndex_Light_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Light_type.c_str());
    int nFieldIndex_Light_dir = DBFGetFieldIndex(dbhHandle, c_strFieldName_Light_dir.c_str());
    int nFieldIndex_LightArray = DBFGetFieldIndex(dbhHandle, c_strFieldName_LightArray.c_str());
    int nFieldIndex_LightCount = DBFGetFieldIndex(dbhHandle, c_strFieldName_LightCount.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        ObjTrafficLight tlTrafficLight = {};
        tlTrafficLight.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        tlTrafficLight.dHeading = Utils::StringToNum<double>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Heading));
        tlTrafficLight.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Light_type);
        tlTrafficLight.strDir = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Light_dir);
        tlTrafficLight.nArray = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_LightArray);
        tlTrafficLight.nCount = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_LightCount);

        // nParts must be 1
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                tlTrafficLight.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLinkIdVctTrafficLight[lRoadID].push_back(tlTrafficLight);

        std::vector<HdLaneId> vctLaneIdTmp;
        AnalyseStrNums(strLaneIDS, vctLaneIdTmp);
        for (HdLaneId hdLaneId : vctLaneIdTmp) {
            mapOutLaneIdVctTrafficLight[hdLaneId].push_back(tlTrafficLight);
        }
        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

/**
 * 地面箭头预处理
 * @param strPath
 * @param mapOutLaneIdVctObjArrow
 */
void MapParser::ParseOBJArrow(const std::string &strPath, std::map<JfDataId, std::vector<ObjArrow>> &mapOutLaneIdVctObjArrow) {
    std::string strFile_dbf = strPath + c_cOBJ_Arrow_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Arrow_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_LaneID = "LaneID";
    const std::string c_strFieldName_Color = "Color";
    const std::string c_strFieldName_Arrow_type = "Arrow_type";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_LaneID = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneID.c_str());
    int nFieldIndex_Color = DBFGetFieldIndex(dbhHandle, c_strFieldName_Color.c_str());
    int nFieldIndex_Arrow_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Arrow_type.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpObjArrow = SHPReadObject(shhHandle, i);

        // read a dbf data object
        ObjArrow arArrow = {};
        arArrow.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        JfDataId lLaneID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneID));
        arArrow.nColor = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Color);
        arArrow.strType = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Arrow_type);

        // nParts must be 1
        for (int j = 0; j < pshpObjArrow->nParts; ++j) {
            for (int k = 0; k < pshpObjArrow->nVertices; ++k) {
                double dLon = pshpObjArrow->padfX[k];
                double dLat = pshpObjArrow->padfY[k];
                double dAlt = pshpObjArrow->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                arArrow.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLaneIdVctObjArrow[lLaneID].push_back(arArrow);
        SHPDestroyObject(pshpObjArrow);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

/**
 * 交通标牌预处理
 * @param strPath
 * @param mapOutLinkIdVctTrafficSign
 */
void MapParser::ParseOBJTrafficSign(const std::string &strPath, std::map<JfDataId, std::vector<ObjTrafficSign>> &mapOutLinkIdVctTrafficSign) {
    std::string strFile_dbf = strPath + c_cOBJ_TrafficSign_dbf;
    std::string strFile_shp = strPath + c_cOBJ_TrafficSign_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_Shape = "Shape";
    const std::string c_strFieldName_Sign_type = "Sign_type";
    const std::string c_strFieldName_Type1 = "Type1";
    const std::string c_strFieldName_Type2 = "Type2";
    const std::string c_strFieldName_Sign_text = "Sign_text";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_Shape = DBFGetFieldIndex(dbhHandle, c_strFieldName_Shape.c_str());
    int nFieldIndex_Sign_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Sign_type.c_str());
    int nFieldIndex_Type1 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Type1.c_str());
    int nFieldIndex_Type2 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Type2.c_str());
    int nFieldIndex_Sign_text = DBFGetFieldIndex(dbhHandle, c_strFieldName_Sign_text.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjTrafficSign objTrafficSign;
        objTrafficSign.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        objTrafficSign.nShape = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Shape);
        objTrafficSign.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Sign_type);
        objTrafficSign.nType1 = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Type1);
        objTrafficSign.nType2 = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Type2);
        objTrafficSign.strText = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Sign_text);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objTrafficSign.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLinkIdVctTrafficSign[lRoadID].push_back(objTrafficSign);
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 杆状物预处理
 * @param strPath
 * @param mapOutLinkIdVctPole
 */
void MapParser::ParseOBJPole(const std::string &strPath, std::map<JfDataId, std::vector<ObjPole>> &mapOutLinkIdVctPole) {
    std::string strFile_dbf = strPath + c_cOBJ_Pole_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Pole_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_Height = "Height";
    const std::string c_strFieldName_Pole_type2 = "Pole_type2";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_Height = DBFGetFieldIndex(dbhHandle, c_strFieldName_Height.c_str());
    int nFieldIndex_Pole_type2 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Pole_type2.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjPole objPole;
        objPole.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        objPole.height = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Height);
        objPole.poleType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Pole_type2);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objPole.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLinkIdVctPole[lRoadID].push_back(objPole);
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 地面文字预处理
 * @param strPath
 * @param mapOutLaneIdVctText
 */
void MapParser::ParseOBJText(const std::string &strPath, std::map<JfDataId, std::vector<ObjText>> &mapOutLaneIdVctText) {
    std::string strFile_dbf = strPath + c_cOBJ_Text_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Text_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_LaneID = "LaneID";
    const std::string c_strFieldName_Color = "Color";
    const std::string c_strFieldName_Text = "Text";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_LaneID = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneID.c_str());
    int nFieldIndex_Color = DBFGetFieldIndex(dbhHandle, c_strFieldName_Color.c_str());
    int nFieldIndex_Text = DBFGetFieldIndex(dbhHandle, c_strFieldName_Text.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjText objText;
        objText.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lLaneID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneID));
        objText.nColor = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Color);
        objText.strText = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Text);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objText.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        mapOutLaneIdVctText[lLaneID].push_back(objText);
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 地面符号预处理
 * @param strPath
 * @param mapOutLaneIdVctText
 */
void MapParser::ParseOBJSymbol(const std::string &strPath, std::map<JfDataId, std::vector<ObjSymbol>> &mapOutLaneIdVctSymbol) {
    std::string strFile_dbf = strPath + c_cOBJ_Symbol_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Symbol_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_LaneID = "LaneID";
    const std::string c_strFieldName_Color = "Color";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_LaneID = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneID.c_str());
    int nFieldIndex_Color = DBFGetFieldIndex(dbhHandle, c_strFieldName_Color.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjSymbol objSymbol;
        objSymbol.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lLaneID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneID));
        objSymbol.color = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Color);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objSymbol.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        mapOutLaneIdVctSymbol[lLaneID].push_back(objSymbol);
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 上方障碍物预处理
 * @param strPath
 * @param mapOutLaneIdVctText
 */
void MapParser::ParseOBJOverHead(const std::string &strPath, std::map<JfDataId, std::vector<ObjOverHead>> &mapOutLinkIdVctOverHead) {
    std::string strFile_dbf = strPath + c_cOBJ_OverHead_dbf;
    std::string strFile_shp = strPath + c_cOBJ_OverHead_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";
    const std::string c_strFieldName_Height = "Height";
    const std::string c_strFieldName_OH_type = "OH_type";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_Height = DBFGetFieldIndex(dbhHandle, c_strFieldName_Height.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());
    int nFieldIndex_OH_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_OH_type.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjOverHead objOverHead = {};
        objOverHead.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        objOverHead.height = DBFReadDoubleAttribute(dbhHandle, i, nFieldIndex_Height);
        objOverHead.OH_type = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_OH_type);

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objOverHead.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objOverHead.vctvdGeoLink.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctOverHead[lRoadID].push_back(objOverHead);
        }
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 禁止停车区预处理
 * @param strPath
 * @param mapOutLinkIdVctOverHead
 */
void MapParser::ParseOBJNoParking(const std::string &strPath, std::map<JfDataId, std::vector<ObjNoParking>> &mapOutLinkIdVctNoParking) {
    std::string strFile_dbf = strPath + c_cOBJ_NoParking_dbf;
    std::string strFile_shp = strPath + c_cOBJ_NoParking_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjNoParking objNoParking = {};
        objNoParking.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objNoParking.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objNoParking.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctNoParking[lRoadID].push_back(objNoParking);
        }
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 减速带预处理
 * @param strPath
 * @param mapOutLinkIdVctSpeedBump
 */
void MapParser::ParseOBJSpeedBump(const std::string &strPath, std::map<JfDataId, std::vector<ObjSpeedBump>> &mapOutLinkIdVctSpeedBump) {
    std::string strFile_dbf = strPath + c_cOBJ_SpeedBump_dbf;
    std::string strFile_shp = strPath + c_cOBJ_SpeedBump_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjSpeedBump objSpeedBump = {};
        objSpeedBump.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objSpeedBump.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objSpeedBump.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctSpeedBump[lRoadID].push_back(objSpeedBump);
        }
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 停车区预处理
 * @param strPath
 * @param mapOutLinkIdVctParking
 */
void MapParser::ParseOBJParking(const std::string &strPath, std::map<JfDataId, std::vector<ObjParking>> &mapOutLinkIdVctParking) {
    std::string strFile_dbf = strPath + c_cOBJ_Parking_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Parking_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjParking objParking = {};
        objParking.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objParking.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objParking.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctParking[lRoadID].push_back(objParking);
        }
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 导流区预处理
 * @param strPath
 * @param mapOutLinkIdVctFillArea
 */
void MapParser::ParseOBJFillArea(const std::string &strPath, std::map<JfDataId, std::vector<ObjFillArea>> &mapOutLinkIdVctFillArea) {
    std::string strFile_dbf = strPath + c_cOBJ_FillArea_dbf;
    std::string strFile_shp = strPath + c_cOBJ_FillArea_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjFillArea objFillArea = {};
        objFillArea.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objFillArea.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objFillArea.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctFillArea[lRoadID].push_back(objFillArea);
        }
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 消防栓预处理
 * @param strPath
 * @param mapOutLinkIdVctHydrant
 */
void MapParser::ParseOBJHydrant(const std::string &strPath, std::map<JfDataId, std::vector<ObjHydrant>> &mapOutLinkIdVctHydrant) {
    std::string strFile_dbf = strPath + c_cOBJ_Hydrant_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Hydrant_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjHydrant objHydrant = {};
        objHydrant.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objHydrant.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objHydrant.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctHydrant[lRoadID].push_back(objHydrant);
        }
        SHPDestroyObject(pshpObj);
    }
}

/**
 * 公交站预处理
 * @param strPath
 * @param mapOutLinkIdVctBusStop
 */
void MapParser::ParseOBJBusStop(const std::string &strPath, std::map<JfDataId, std::vector<ObjBusStop>> &mapOutLinkIdVctBusStop) {
    std::string strFile_dbf = strPath + c_cOBJ_BusStop_dbf;
    std::string strFile_shp = strPath + c_cOBJ_BusStop_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJText(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJArrow(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        ObjBusStop objBusStop = {};
        objBusStop.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));

        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);
        AnalyseStrNums(strLaneIDS, objBusStop.vctlLaneId);

        std::string lRoadIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDS;
        AnalyseStrNums(lRoadIDS, vctlRoadIDS);

        // read a shp data object
        SHPObject *pshpObj = SHPReadObject(shhHandle, i);
        // nParts must be 1
        for (int j = 0; j < pshpObj->nParts; ++j) {
            for (int k = 0; k < pshpObj->nVertices; ++k) {
                double dLon = pshpObj->padfX[k];
                double dLat = pshpObj->padfY[k];
                double dAlt = pshpObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                objBusStop.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }
        for (JfDataId lRoadID : vctlRoadIDS) {
            mapOutLinkIdVctBusStop[lRoadID].push_back(objBusStop);
        }
        SHPDestroyObject(pshpObj);
    }
}

void MapParser::ParseOBJPoint(const std::string &strPath, std::map<JfDataId, std::vector<ObjPoint>> &mapOutLinkIdVctPoint) {
    std::string strFile_dbf = strPath + c_cOBJ_Symbol_dbf;
    std::string strFile_shp = strPath + c_cOBJ_Symbol_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseOBJSymbol(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseOBJSymbol(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_OBJID = "OBJID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_LANE_IDS = "LANE_IDS";
    const std::string c_strFieldName_OBJ_type = "OBJ_type";
    const std::string c_strFieldName_Memo1 = "Memo1";
    const std::string c_strFieldName_Memo2 = "Memo2";
    const std::string c_strFieldName_Memo3 = "Memo3";
    const std::string c_strFieldName_Memo4 = "Memo4";

    int nFieldIndex_OBJID = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_LANE_IDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LANE_IDS.c_str());
    int nFieldIndex_OBJ_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_OBJ_type.c_str());
    int nFieldIndex_Memo1 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Memo1.c_str());
    int nFieldIndex_Memo2 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Memo2.c_str());
    int nFieldIndex_Memo3 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Memo3.c_str());
    int nFieldIndex_Memo4 = DBFGetFieldIndex(dbhHandle, c_strFieldName_Memo4.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        ObjPoint ptPoint = {};
        ptPoint.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_OBJID));
        JfDataId lRoadID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LANE_IDS);
        AnalyseStrNums(strLaneIDS, ptPoint.vctlLaneId);
        ptPoint.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_OBJ_type);
        ptPoint.strMemo1 = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Memo1);
        ptPoint.strMemo2 = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Memo2);
        ptPoint.strMemo3 = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Memo3);
        ptPoint.strMemo4 = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Memo4);

        // nParts must be 1
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                ptPoint.vctdGeoNode = std::vector<double>{dLon, dLat, dAlt};
            }
        }

        mapOutLinkIdVctPoint[lRoadID].push_back(ptPoint);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseRoadCrossArea(const std::string &strPath, std::map<JfDataId, std::vector<RoadCrossArea>> &mapOutLinkIdVctCrossArea) {
    std::string strFile_dbf = strPath + c_cRoad_CrossArea_dbf;
    std::string strFile_shp = strPath + c_cRoad_CrossArea_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseRoadCrossArea(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseRCrossArea(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_Cross_ID = "Cross_ID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";

    int nFieldIndex_Cross_ID = DBFGetFieldIndex(dbhHandle, c_strFieldName_Cross_ID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        RoadCrossArea caCrossArea = {};
        caCrossArea.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Cross_ID));
        std::string strRoadID = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);
        std::vector<JfDataId> vctlRoadIDs = {};
        AnalyseStrNums(strRoadID, vctlRoadIDs);

        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                // double dM = pshpRCrossAreaObj->padfM[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                caCrossArea.vctvdGeoArea.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        for (JfDataId lRoadID : vctlRoadIDs) {
            mapOutLinkIdVctCrossArea[lRoadID].push_back(caCrossArea);
        }

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseJunction(const std::string &strPath, std::map<JfDataId, RoadJunction> &mapOutIdJunction) {
    std::string strFile_dbf = strPath + c_cJunction_dbf;
    std::string strFile_shp = strPath + c_cJunction_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseJunction(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseJunction(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_JCID = "JCID";
    const std::string c_strFieldName_RoadIDS = "RoadIDS";

    int nFieldIndex_JCID = DBFGetFieldIndex(dbhHandle, c_strFieldName_JCID.c_str());
    int nFieldIndex_RoadIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        RoadJunction jcJunction = {};
        jcJunction.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_JCID));
        std::string strRoadIds = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadIDS);

        // nParts is 0, so ignore it
        // for (int j = 0; j < pshpJunctionObj->nParts; ++j)
        {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                // double dM = pshpJunctionObj->padfM[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                jcJunction.vctdGeoNode = std::vector<double>{dLon, dLat, dAlt};
            }
        }

        mapOutIdJunction[jcJunction.lId] = jcJunction;

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseRoadEdgeNode(const std::string &strPath, std::map<JfDataId, RoadEdgeNode> &mapOutIdEdgeNode) {
    std::string strFile_dbf = strPath + c_cRoad_EdgeNode_dbf;
    std::string strFile_shp = strPath + c_cRoad_EdgeNode_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseRoadEdgeNode(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseREdgeNode(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_RE_NodeID = "RE_NodeID";
    const std::string c_strFieldName_REdgeIDS = "REdgeIDS";

    int nFieldIndex_RE_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RE_NodeID.c_str());
    int nFieldIndex_REdgeIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_REdgeIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        RoadEdgeNode enEdgeNode = {};
        enEdgeNode.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RE_NodeID));
        std::string strREdgeIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_REdgeIDS);

        // nParts is 0, so ignore it
        // for (int j = 0; j < pshpJunctionObj->nParts; ++j)
        {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                // double dM = pshpJunctionObj->padfM[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                enEdgeNode.vctdGeoNode = std::vector<double>{dLon, dLat, dAlt};
            }
        }

        mapOutIdEdgeNode[enEdgeNode.lId] = enEdgeNode;

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseRoadEdgeLink(const std::string &strPath, const std::map<JfDataId, RoadEdgeNode> &mapIdEdgeNode, std::map<JfDataId, RoadEdge> &mapOutIdEdge) {
    std::string strFile_dbf = strPath + c_cRoad_EdgeLink_dbf;
    std::string strFile_shp = strPath + c_cRoad_EdgeLink_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseRoadEdgeLink(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseRoadEdgeLink(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_REdgeID = "REdgeID";
    const std::string c_strFieldName_SRE_NodeID = "SRE_NodeID";
    const std::string c_strFieldName_ERE_NodeID = "ERE_NodeID";
    const std::string c_strFieldName_REdge_type = "REdge_type";
    const std::string c_strFieldName_REdgeColor = "REdgeColor";

    int nFieldIndex_REdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_REdgeID.c_str());
    int nFieldIndex_SRE_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_SRE_NodeID.c_str());
    int nFieldIndex_ERE_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_ERE_NodeID.c_str());
    int nFieldIndex_REdge_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_REdge_type.c_str());
    int nFieldIndex_REdgeColor = DBFGetFieldIndex(dbhHandle, c_strFieldName_REdgeColor.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        RoadEdge elEdgeLink = {};
        elEdgeLink.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_REdgeID));
        JfDataId lSRE_NodeID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_SRE_NodeID));
        Point ptStart = {};
        if (mapIdEdgeNode.find(lSRE_NodeID) != mapIdEdgeNode.end()) {
            elEdgeLink.enStartNode = mapIdEdgeNode.at(lSRE_NodeID);
            ptStart = elEdgeLink.enStartNode.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseRoadEdgeLink(), could not find Road_EdgeNode lValue = {0}, Road_EdgeLink lValue = {1}", lSRE_NodeID, elEdgeLink.lREdgeID);
        }
        Point ptEnd = {};
        JfDataId lERE_NodeID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_ERE_NodeID));
        if (mapIdEdgeNode.find(lERE_NodeID) != mapIdEdgeNode.end()) {
            elEdgeLink.enEndNode = mapIdEdgeNode.at(lERE_NodeID);
            ptEnd = elEdgeLink.enEndNode.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseRoadEdgeLink(), could not find Road_EdgeNode lValue = {0}, Road_EdgeLink lValue = {1}", lERE_NodeID, elEdgeLink.lREdgeID);
        }
        elEdgeLink.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_REdge_type);
        elEdgeLink.nColor = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_REdgeColor);

        // nParts is 0, so ignore it
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                // double dM = pshpJunctionObj->padfM[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                elEdgeLink.vctvdGeoLink.push_back(std::vector<double>{dLon, dLon, dLat, dAlt});
            }
        }

        // insert the start and end node if not exist in the egolink
        // if (ptStart != Point() && ptStart.dLon != Point(elEdgeLink.vctvdGeoLink.at(0)).dLon && ptStart.dLat != Point(elEdgeLink.vctvdGeoLink.at(0)).dLat) {
        //     elEdgeLink.vctvdGeoLink.insert(elEdgeLink.vctvdGeoLink.begin(), elEdgeLink.enStartNode.vctdGeoNode);
        // }
        // if (ptEnd != Point() && ptEnd.dLon != Point(elEdgeLink.vctvdGeoLink.at(elEdgeLink.vctvdGeoLink.size() - 1)).dLon && ptEnd.dLat != Point(elEdgeLink.vctvdGeoLink.at(elEdgeLink.vctvdGeoLink.size() - 1)).dLat) {
        //     elEdgeLink.vctvdGeoLink.insert(elEdgeLink.vctvdGeoLink.end(), elEdgeLink.enEndNode.vctdGeoNode);
        // }

        mapOutIdEdge[elEdgeLink.lId] = elEdgeLink;

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseRoad(const std::string &strPath, const std::map<JfDataId, std::vector<ObjPole>> mapLinkIdVctPole, const std::map<JfDataId, std::vector<ObjStopLine>> mapLinkIdVctStopLine,
                          const std::map<JfDataId, std::vector<ObjCrossing>> mapLinkIdVctCrossing, const std::map<JfDataId, std::vector<ObjTrafficLight>> mapLinkIdVctTrafficLight,
                          const std::map<JfDataId, std::vector<ObjTrafficSign>> mapLinkIdVctTrafficSign, const std::map<JfDataId, std::vector<ObjOverHead>> mapLinkIdVctOverHead, const std::map<JfDataId, std::vector<ObjFillArea>> mapLinkIdVctFillArea,
                          const std::map<JfDataId, std::vector<ObjBusStop>> mapLinkIdVctBusStop, const std::map<JfDataId, std::vector<ObjHydrant>> mapLinkIdVctHydrant, const std::map<JfDataId, std::vector<ObjParking>> mapLinkIdVctParking,
                          const std::map<JfDataId, std::vector<ObjSpeedBump>> mapLinkIdVctSpeedBump, const std::map<JfDataId, std::vector<ObjNoParking>> mapLinkIdVctNoParking, const std::map<JfDataId, std::vector<RoadCrossArea>> &mapLinkIdVctCrossArea,
                          const std::map<JfDataId, std::vector<ObjPoint>> mapLinkIdVctPoint, const std::map<JfDataId, RoadJunction> &mapIdJunction, const std::map<JfDataId, RoadEdge> &mapIdEdge, std::map<JfDataId, HdLink> &mapOutIdHdLink,
                          ShpBound &bdOutBound) {
    std::string strFile_dbf = strPath + c_cRoad_dbf;
    std::string strFile_shp = strPath + c_cRoad_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseRoad(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseRoad(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_SJCID = "SJCID";
    const std::string c_strFieldName_EJCID = "EJCID";
    const std::string c_strFieldName_L_REdgeID = "L_REdgeID";
    const std::string c_strFieldName_R_REdgeID = "R_REdgeID";
    const std::string c_strFieldName_Length = "Length";
    const std::string c_strFieldName_Lane_num = "Lane_num";
    const std::string c_strFieldName_Direction = "Direction";
    const std::string c_strFieldName_Road_rank = "Road_rank";
    const std::string c_strFieldName_Road_type = "Road_type";
    const std::string c_strFieldName_Startangle = "Startangle";
    const std::string c_strFieldName_Name_chn = "Name_chn";
    const std::string c_strFieldName_Speed = "Speed";

    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_SJCID = DBFGetFieldIndex(dbhHandle, c_strFieldName_SJCID.c_str());
    int nFieldIndex_EJCID = DBFGetFieldIndex(dbhHandle, c_strFieldName_EJCID.c_str());
    int nFieldIndex_L_REdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_L_REdgeID.c_str());
    int nFieldIndex_R_REdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_R_REdgeID.c_str());
    int nFieldIndex_Length = DBFGetFieldIndex(dbhHandle, c_strFieldName_Length.c_str());
    int nFieldIndex_Lane_num = DBFGetFieldIndex(dbhHandle, c_strFieldName_Lane_num.c_str());
    int nFieldIndex_Direction = DBFGetFieldIndex(dbhHandle, c_strFieldName_Direction.c_str());
    int nFieldIndex_Road_rank = DBFGetFieldIndex(dbhHandle, c_strFieldName_Road_rank.c_str());
    int nFieldIndex_Road_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Road_type.c_str());
    int nFieldIndex_Startangle = DBFGetFieldIndex(dbhHandle, c_strFieldName_Startangle.c_str());
    int nFieldIndex_Name_chn = DBFGetFieldIndex(dbhHandle, c_strFieldName_Name_chn.c_str());
    int nFieldIndex_Speed = DBFGetFieldIndex(dbhHandle, c_strFieldName_Speed.c_str());

    // LogicEvaluator logic_evaluator(MapConfig::map_road_filer_logic);

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        HdLink hlLink = {};
        JfDataId lRoadId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        JfDataId lSJCID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_SJCID));
        Point ptStart = {};
        if (mapIdJunction.find(lSJCID) != mapIdJunction.end()) {
            hlLink.jcStartJunc = mapIdJunction.at(lSJCID);
            ptStart = hlLink.jcStartJunc.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseRoad(), could not find Junction lValue = {0}, Road lValue = {1}", lSJCID, lRoadId);
        }
        JfDataId lEJCID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EJCID));
        Point ptEnd = {};
        if (mapIdJunction.find(lEJCID) != mapIdJunction.end()) {
            hlLink.jcEndJunc = mapIdJunction.at(lEJCID);
            ptEnd = hlLink.jcEndJunc.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseRoad(), could not find Junction lValue = {0}, Road lValue = {1}", lEJCID, lRoadId);
        }
        std::string strL_REdgeID = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_L_REdgeID);
        std::vector<JfDataId> vctlL_REdgeIDs = {};
        AnalyseStrNums(strL_REdgeID, vctlL_REdgeIDs);
        for (JfDataId lL_REdgeID : vctlL_REdgeIDs) {
            if (mapIdEdge.find(lL_REdgeID) != mapIdEdge.end()) {
                hlLink.vctreLeftEdge.push_back(mapIdEdge.at(lL_REdgeID));
            } else {
                // jf_log_error("MapParser::ParseRoad(), could not find Road_EdgeLink lValue = {0}, Road lValue = {1}", lL_REdgeID, lRoadId);
            }
        }
        std::string strR_REdgeID = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_R_REdgeID);
        std::vector<JfDataId> vctlR_REdgeIDs = {};
        AnalyseStrNums(strR_REdgeID, vctlR_REdgeIDs);
        for (JfDataId lR_REdgeID : vctlR_REdgeIDs) {
            if (mapIdEdge.find(lR_REdgeID) != mapIdEdge.end()) {
                hlLink.vctreRightEdge.push_back(mapIdEdge.at(lR_REdgeID));
            } else {
                // jf_log_error("MapParser::ParseRoad(), could not find Road_EdgeLink lValue = {0}, Road lValue = {1}", lR_REdgeID, lRoadId);
            }
        }
        hlLink.dLength = DBFReadDoubleAttribute(dbhHandle, i, nFieldIndex_Length);
        hlLink.nLaneNum = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Lane_num);
        hlLink.nDirection = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Direction);
        hlLink.nRank = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Road_rank);
        hlLink.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Road_type);
        hlLink.dStartAngle = DBFReadDoubleAttribute(dbhHandle, i, nFieldIndex_Startangle);
        hlLink.strName = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Name_chn);
        hlLink.nSpeedLimit = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Speed);

        // nParts must be 1
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                // double dM = pshpRoadObj->padfM[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                hlLink.vctvdGeoLink.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        // insert the start and end node if not exist in the egolink
        // if (ptStart != Point() && ptStart.dLon != Point(hlLink.vctvdGeoLink.at(0)).dLon && ptStart.dLat != Point(hlLink.vctvdGeoLink.at(0)).dLat) {
        //     hlLink.vctvdGeoLink.insert(hlLink.vctvdGeoLink.begin(), hlLink.jcStartJunc.vctdGeoNode);
        // }
        // if (ptEnd != Point() && ptEnd.dLon != Point(hlLink.vctvdGeoLink.at(hlLink.vctvdGeoLink.size() - 1)).dLon && ptEnd.dLat != Point(hlLink.vctvdGeoLink.at(hlLink.vctvdGeoLink.size() - 1)).dLat) {
        //     hlLink.vctvdGeoLink.insert(hlLink.vctvdGeoLink.end(), hlLink.jcEndJunc.vctdGeoNode);
        // }

        /********对象数据的赋值************/
        if (mapLinkIdVctTrafficSign.find(lRoadId) != mapLinkIdVctTrafficSign.end()) {
            hlLink.vctTrafficSign = mapLinkIdVctTrafficSign.at(lRoadId);
        }
        if (mapLinkIdVctPole.find(lRoadId) != mapLinkIdVctPole.end()) {
            hlLink.vctPole = mapLinkIdVctPole.at(lRoadId);
        }
        if (mapLinkIdVctStopLine.find(lRoadId) != mapLinkIdVctStopLine.end()) {
            hlLink.vctslStopLine = mapLinkIdVctStopLine.at(lRoadId);
        }
        if (mapLinkIdVctCrossing.find(lRoadId) != mapLinkIdVctCrossing.end()) {
            hlLink.vctcrCrossing = mapLinkIdVctCrossing.at(lRoadId);
        }
        if (mapLinkIdVctTrafficLight.find(lRoadId) != mapLinkIdVctTrafficLight.end()) {
            hlLink.vcttlTrafficLight = mapLinkIdVctTrafficLight.at(lRoadId);
        }
        if (mapLinkIdVctOverHead.find(lRoadId) != mapLinkIdVctOverHead.end()) {
            hlLink.vctOverHead = mapLinkIdVctOverHead.at(lRoadId);
        }
        if (mapLinkIdVctNoParking.find(lRoadId) != mapLinkIdVctNoParking.end()) {
            hlLink.vctNoParking = mapLinkIdVctNoParking.at(lRoadId);
        }
        if (mapLinkIdVctSpeedBump.find(lRoadId) != mapLinkIdVctSpeedBump.end()) {
            hlLink.vctSpeedBump = mapLinkIdVctSpeedBump.at(lRoadId);
        }
        if (mapLinkIdVctParking.find(lRoadId) != mapLinkIdVctParking.end()) {
            hlLink.vctParking = mapLinkIdVctParking.at(lRoadId);
        }
        if (mapLinkIdVctFillArea.find(lRoadId) != mapLinkIdVctFillArea.end()) {
            hlLink.vctFillArea = mapLinkIdVctFillArea.at(lRoadId);
        }
        if (mapLinkIdVctHydrant.find(lRoadId) != mapLinkIdVctHydrant.end()) {
            hlLink.vctHydrant = mapLinkIdVctHydrant.at(lRoadId);
        }
        if (mapLinkIdVctBusStop.find(lRoadId) != mapLinkIdVctBusStop.end()) {
            hlLink.vctBusStop = mapLinkIdVctBusStop.at(lRoadId);
        }
        if (mapLinkIdVctPoint.find(lRoadId) != mapLinkIdVctPoint.end()) {
            hlLink.vctRsuPoint = mapLinkIdVctPoint.at(lRoadId);
        }
        if (mapLinkIdVctCrossArea.find(lRoadId) != mapLinkIdVctCrossArea.end()) {
            hlLink.vctcaCrossArea = mapLinkIdVctCrossArea.at(lRoadId);
        }

        mapOutIdHdLink[lRoadId] = hlLink;

        // std::map<std::string, std::string> logic_map{
        //     {"RoadID", jf::to_string(lRoadId)},
        //     {"rank", jf::to_string(rdRoad.nRank)},
        //     {"length", jf::to_string(rdRoad.dLength)},
        //     {"nLaneNum", jf::to_string(rdRoad.nLaneNum)},
        //     {"direction", jf::to_string(rdRoad.nDirection)},
        //     {"type", jf::to_string(rdRoad.nType)},
        //     {"dStartAngle", jf::to_string(rdRoad.dStartAngle)},
        //     {"speed", jf::to_string(rdRoad.nSpeed)},
        // };
        // if (logic_evaluator.IsValid(logic_map)) {
        //     mapIdRoad[lRoadId] = rdRoad;
        // }

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseHDEdgeNode(const std::string &strPath, std::map<JfDataId, HdEdgeNode> &mapOutIdHdEdgeNode) {
    std::string strFile_dbf = strPath + c_cHD_EdgeNode_dbf;
    std::string strFile_shp = strPath + c_cHD_EdgeNode_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseEdgeNode(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseEdgeNode(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_EdgeNodeID = "EdgeNodeID";
    const std::string c_strFieldName_EdgeIDS = "EdgeIDS";

    int nFieldIndex_EdgeNodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_EdgeNodeID.c_str());
    int nFieldIndex_EdgeIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_EdgeIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        HdEdgeNode enEdgeNode = {};
        enEdgeNode.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EdgeNodeID));
        std::string strEdgeIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EdgeIDS);

        // nParts is 0 so ignore it
        // for (int j = 0; j < pshpEdgeNodeObj->nParts; ++j)
        {
            // nVertices must be 1
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                enEdgeNode.vctdGeoNode = std::vector<double>{dLon, dLat, dAlt};
            }
        }

        mapOutIdHdEdgeNode[enEdgeNode.lId] = enEdgeNode;

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseHDLaneMark(const std::string &strPath, std::map<JfDataId, std::vector<HdLaneMark>> &mapOutEdgeIdVctLaneMark) {
    std::string strFile_dbf = strPath + c_cHD_LaneMark_dbf;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    if (nullptr == dbhHandle) {
        // jf_log_error("MapParser::ParseLaneMark(), invalid map file path, could not open.");
        return;
    }

    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (0 == nRcdCnt) {
        // jf_log_error("MapParser::ParseLaneMark(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_MarkID = "MarkID";
    const std::string c_strFieldName_EdgeID = "EdgeID";
    const std::string c_strFieldName_Mark_no = "Mark_no";
    const std::string c_strFieldName_Mark_type = "Mark_type";
    const std::string c_strFieldName_Mark_color = "Mark_color";
    const std::string c_strFieldName_Mark_width = "Mark_width";

    int nFieldIndex_MarkID = DBFGetFieldIndex(dbhHandle, c_strFieldName_MarkID.c_str());
    int nFieldIndex_EdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_EdgeID.c_str());
    int nFieldIndex_Mark_no = DBFGetFieldIndex(dbhHandle, c_strFieldName_Mark_no.c_str());
    int nFieldIndex_Mark_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Mark_type.c_str());
    int nFieldIndex_Mark_color = DBFGetFieldIndex(dbhHandle, c_strFieldName_Mark_color.c_str());
    int nFieldIndex_Mark_width = DBFGetFieldIndex(dbhHandle, c_strFieldName_Mark_width.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a dbf data object
        HdLaneMark lmLaneMark = {};
        lmLaneMark.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_MarkID));
        JfDataId lEdgeId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EdgeID));
        lmLaneMark.nNum = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Mark_no);
        lmLaneMark.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Mark_type);
        lmLaneMark.nColor = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Mark_color);
        lmLaneMark.nWidth = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Mark_width);

        mapOutEdgeIdVctLaneMark[lEdgeId].push_back(lmLaneMark);
    }

    DBFClose(dbhHandle);
}

void MapParser::ParseHDEdgeLink(const std::string &strPath, const std::map<JfDataId, HdEdgeNode> &mapIdEdgeNode, const std::map<JfDataId, std::vector<HdLaneMark>> &mapEdgeIdVctLaneMark, const std::map<JfDataId, HdEdge> &mapIdEdge,
                                std::map<JfDataId, HdLink> &mapOutIdHdLink) {
    std::string strFile_dbf = strPath + c_cHD_EdgeLink_dbf;
    std::string strFile_shp = strPath + c_cHD_EdgeLink_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseEdgeLink(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error(
        //     "MapParser::ParseEdgeLink(), invalid map file content, could not "
        //     "Parse.");
        return;
    }

    const std::string c_strFieldName_EdgeID = "EdgeID";
    const std::string c_strFieldName_SE_NodeID = "SE_NodeID";
    const std::string c_strFieldName_EE_NodeID = "EE_NodeID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_Edge_no = "Edge_no";
    const std::string c_strFieldName_Edge_type = "Edge_type";
    const std::string c_strFieldName_Edge_cross = "Edge_cross";
    const std::string c_strFieldName_Mark_count = "Mark_count";

    int nFieldIndex_EdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_EdgeID.c_str());
    int nFieldIndex_SE_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_SE_NodeID.c_str());
    int nFieldIndex_EE_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_EE_NodeID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_Edge_no = DBFGetFieldIndex(dbhHandle, c_strFieldName_Edge_no.c_str());
    int nFieldIndex_Edge_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Edge_type.c_str());
    int nFieldIndex_Edge_cross = DBFGetFieldIndex(dbhHandle, c_strFieldName_Edge_cross.c_str());
    int nFieldIndex_Mark_count = DBFGetFieldIndex(dbhHandle, c_strFieldName_Mark_count.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        HdEdge heEdge = {};
        heEdge.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EdgeID));
        Point ptStart = {};
        JfDataId lSE_NodeID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_SE_NodeID));
        if (mapIdEdgeNode.find(lSE_NodeID) != mapIdEdgeNode.end()) {
            heEdge.enStartNode = mapIdEdgeNode.at(lSE_NodeID);
            ptStart = heEdge.enStartNode.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseEdgeLink(), could not find HD_EdgeNode id = {0}, HD_EdgeLink lValue = {1}", lSE_NodeID, elEdgeLink.lEdgeID);
        }
        JfDataId lEE_NodeID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EE_NodeID));
        Point ptEnd = {};
        if (mapIdEdgeNode.find(lEE_NodeID) != mapIdEdgeNode.end()) {
            heEdge.enEndNode = mapIdEdgeNode.at(lEE_NodeID);
            ptEnd = heEdge.enEndNode.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseEdgeLink(), could not find HD_EdgeNode id = {0}, EdgeId = {1}", lSE_NodeID, elEdgeLink.lEdgeID);
        }
        JfDataId lRoadId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        heEdge.nNum = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Edge_no);
        heEdge.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Edge_type);
        heEdge.nCross = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Edge_cross);
        heEdge.nMarkCount = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Mark_count);

        // nParts must be 1
        for (int j = 0; j < pshpRecord->nParts; ++j) {
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                heEdge.vctvdGeoLink.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        // insert the start and end node if not exist in the egolink
        // if (ptStart != Point() && ptStart.dLon != Point(heEdge.vctvdGeoLink.at(0)).dLon && ptStart.dLat != Point(heEdge.vctvdGeoLink.at(0)).dLat) {
        //     heEdge.vctvdGeoLink.insert(heEdge.vctvdGeoLink.begin(), heEdge.enStartNode.vctdGeoNode);
        // }
        // if (ptEnd != Point() && ptEnd.dLon != Point(heEdge.vctvdGeoLink.at(heEdge.vctvdGeoLink.size() - 1)).dLon && ptEnd.dLat != Point(heEdge.vctvdGeoLink.at(heEdge.vctvdGeoLink.size() - 1)).dLat) {
        //     heEdge.vctvdGeoLink.insert(heEdge.vctvdGeoLink.end(), heEdge.enEndNode.vctdGeoNode);
        // }

        if (mapEdgeIdVctLaneMark.find(heEdge.lId) != mapEdgeIdVctLaneMark.end()) {
            heEdge.vcthmMark = mapEdgeIdVctLaneMark.at(heEdge.lId);
        }

        mapOutIdHdLink[lRoadId].vctheEdge.push_back(heEdge);

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseHDLaneNode(const std::string &strPath, std::map<JfDataId, HdLaneNode> &mapOutIdHdLaneNode) {
    std::string strFile_dbf = strPath + c_cHD_LaneNode_dbf;
    std::string strFile_shp = strPath + c_cHD_LaneNode_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseHDLaneNode(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseLaneNode(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_LaneNodeID = "LaneNodeID";
    const std::string c_strFieldName_LaneIDS = "LaneIDS";

    int nFieldIndex_LaneNodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneNodeID.c_str());
    int nFieldIndex_LaneIDS = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneIDS.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpRecord = SHPReadObject(shhHandle, i);

        // read a dbf data object
        HdLaneNode lnLaneNode = {};
        lnLaneNode.lId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneNodeID));
        std::string strLaneIDS = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneIDS);

        // nParts is 0 so ignore it
        // for (int j = 0; j < pshpLaneNodeObj->nParts; ++j)
        {
            // nVertices must be 1
            for (int k = 0; k < pshpRecord->nVertices; ++k) {
                double dLon = pshpRecord->padfX[k];
                double dLat = pshpRecord->padfY[k];
                double dAlt = pshpRecord->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                lnLaneNode.vctdGeoNode = std::vector<double>{dLon, dLat, dAlt};
            }
        }

        mapOutIdHdLaneNode[lnLaneNode.lId] = lnLaneNode;

        SHPDestroyObject(pshpRecord);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::ParseLaneADAS(const std::string &strPath, std::map<JfDataId, std::vector<HdLaneAdas>> &mapOutLaneIdVctHdLaneAdas) {
    std::string strFile_csv = strPath + c_cLaneADAS_csv;

    std::ifstream ifsLaneADAS(strFile_csv, std::ios::in);
    if (!ifsLaneADAS) {
        // jf_log_error("sdGlParser::ParseLaneADAS(), invalid map file path, could not open.");
        return;
    }

    int i = 0;
    std::string strLine = {};
    std::string strField = {};

    getline(ifsLaneADAS, strLine);  // 将整行数据读取到sin流中，第一行是是说明文，不用

    while (getline(ifsLaneADAS, strLine))  // 按行读取csv文件中的数据
    {
        strLine = strLine.substr(0, strLine.length() - 1);  // 去掉最后的换行符

        HdLaneAdas laLaneAdas = {};

        std::istringstream ssStreamIn(strLine);  // 将整行数据读取到sin流中

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，id
        JfDataId lLaneID = Utils::StringToNum<JfDataId>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，meshId
        double _ = Utils::StringToNum<double>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，Seq_num
        laLaneAdas.nSeqNum = Utils::StringToNum<int>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，Latitude
        laLaneAdas.dLat = Utils::StringToNum<double>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，Longitude
        laLaneAdas.dLon = Utils::StringToNum<double>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，outCurvature
        laLaneAdas.dOutCurvature = Utils::StringToNum<double>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，outRoll
        laLaneAdas.dOutRoll = Utils::StringToNum<double>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，outPitch
        laLaneAdas.dOutPitch = Utils::StringToNum<double>(strField);

        getline(ssStreamIn, strField, ',');  // 将字符串流sin中的的字符读取到field中，以逗号分割，outAzminuth
        laLaneAdas.dOutAzimuth = Utils::StringToNum<double>(strField);

        mapOutLaneIdVctHdLaneAdas[lLaneID].push_back(laLaneAdas);
    }

    ifsLaneADAS.close();
}

void MapParser::ParseHDLaneLink(const std::string &strPath, const std::map<JfDataId, HdLaneNode> &mapIdHdLaneNode, const std::map<JfDataId, std::vector<HdLaneAdas>> &mapIdVctHdLaneAdas, const std::map<JfDataId, std::vector<ObjArrow>> &mapIdVctObjArrow,
                                const std::map<JfDataId, std::vector<ObjTrafficLight>> &mapLaneIdVctTrafficLight, const std::map<JfDataId, std::vector<ObjText>> &mapLaneIdVctText, const std::map<JfDataId, std::vector<ObjSymbol>> &mapLaneIdVctSymbol,
                                std::map<JfDataId, HdLink> &mapOutIdHdLink) {
    std::string strFile_dbf = strPath + c_cHD_LaneLink_dbf;
    std::string strFile_shp = strPath + c_cHD_LaneLink_shp;

    DBFHandle dbhHandle = DBFOpen(strFile_dbf.c_str(), "rb");
    SHPHandle shhHandle = SHPOpen(strFile_shp.c_str(), "rb");
    if ((nullptr == shhHandle) || (nullptr == dbhHandle)) {
        // jf_log_error("MapParser::ParseLaneLink(), invalid map file path, could not open.");
        return;
    }

    int nEntities = 0;
    int nShapeType = 0;
    double dMinBound[4] = {};
    double dMaxBound[4] = {};
    SHPGetInfo(shhHandle, &nEntities, &nShapeType, dMinBound, dMaxBound);
    int nRcdCnt = DBFGetRecordCount(dbhHandle);
    if (nEntities != nRcdCnt) {
        // jf_log_error("MapParser::ParseLaneLink(), invalid map file content, could not Parse.");
        return;
    }

    const std::string c_strFieldName_LaneID = "LaneID";
    const std::string c_strFieldName_SL_NodeID = "SL_NodeID";
    const std::string c_strFieldName_EL_NodeID = "EL_NodeID";
    const std::string c_strFieldName_L_EdgeID = "L_EdgeID";
    const std::string c_strFieldName_R_EdgeID = "R_EdgeID";
    const std::string c_strFieldName_RoadID = "RoadID";
    const std::string c_strFieldName_Lane_no = "Lane_no";
    const std::string c_strFieldName_Direction = "Direction";
    const std::string c_strFieldName_Lane_type = "Lane_type";
    const std::string c_strFieldName_Arrow = "Arrow";
    const std::string c_strFieldName_Lane_width = "Lane_width";
    const std::string c_strFieldName_Speed = "Speed";
    const std::string c_strFieldName_Speed_min = "Speed_min";

    int nFieldIndex_LaneID = DBFGetFieldIndex(dbhHandle, c_strFieldName_LaneID.c_str());
    int nFieldIndex_SL_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_SL_NodeID.c_str());
    int nFieldIndex_EL_NodeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_EL_NodeID.c_str());
    int nFieldIndex_L_EdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_L_EdgeID.c_str());
    int nFieldIndex_R_EdgeID = DBFGetFieldIndex(dbhHandle, c_strFieldName_R_EdgeID.c_str());
    int nFieldIndex_RoadID = DBFGetFieldIndex(dbhHandle, c_strFieldName_RoadID.c_str());
    int nFieldIndex_Lane_no = DBFGetFieldIndex(dbhHandle, c_strFieldName_Lane_no.c_str());
    int nFieldIndex_Direction = DBFGetFieldIndex(dbhHandle, c_strFieldName_Direction.c_str());
    int nFieldIndex_Lane_type = DBFGetFieldIndex(dbhHandle, c_strFieldName_Lane_type.c_str());
    int nFieldIndex_Arrow = DBFGetFieldIndex(dbhHandle, c_strFieldName_Arrow.c_str());
    int nFieldIndex_Lane_width = DBFGetFieldIndex(dbhHandle, c_strFieldName_Lane_width.c_str());
    int nFieldIndex_Speed = DBFGetFieldIndex(dbhHandle, c_strFieldName_Speed.c_str());
    int nFieldIndex_Speed_min = DBFGetFieldIndex(dbhHandle, c_strFieldName_Speed_min.c_str());

    for (int i = 0; i < nRcdCnt; ++i) {
        // read a shp data object
        SHPObject *pshpHDLaneLinkObj = SHPReadObject(shhHandle, i);

        // read a dbf data object
        HdLane hlLane = {};
        hlLane.liId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_LaneID));
        JfDataId lSL_NodeID = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_SL_NodeID));
        Point ptStart = {};
        if (mapIdHdLaneNode.find(lSL_NodeID) != mapIdHdLaneNode.end()) {
            hlLane.lnStartNode = mapIdHdLaneNode.at(lSL_NodeID);
            ptStart = hlLane.lnStartNode.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseRoad(), could not find HD_LaneNode id = {0}, HD_LaneLink lValue = {1}", lSL_NodeID, llLaneLink.lLaneID);
        }
        JfDataId lEL_NodeId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_EL_NodeID));
        Point ptEnd = {};
        if (mapIdHdLaneNode.find(lEL_NodeId) != mapIdHdLaneNode.end()) {
            hlLane.lnEndNode = mapIdHdLaneNode.at(lEL_NodeId);
            ptEnd = hlLane.lnEndNode.vctdGeoNode;
        } else {
            // jf_log_error("MapParser::ParseRoad(), could not find HD_LaneNode id = {0}, HD_LaneLink lValue = {1}", lEL_NodeId, llLaneLink.lLaneID);
        }
        hlLane.nSeqNum = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Lane_no);
        hlLane.lLeftEdgeId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_L_EdgeID));
        hlLane.lRightEdgeId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_R_EdgeID));

        JfDataId lRoadId = Utils::StringToNum<JfDataId>(DBFReadStringAttribute(dbhHandle, i, nFieldIndex_RoadID));
        hlLane.nDirection = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Direction);
        hlLane.nType = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Lane_type);
        hlLane.strArrows = DBFReadStringAttribute(dbhHandle, i, nFieldIndex_Arrow);
        hlLane.nWidth = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Lane_width);
        hlLane.nMaxSpeed = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Speed);
        hlLane.nMinSpeed = DBFReadIntegerAttribute(dbhHandle, i, nFieldIndex_Speed_min);

        // nParts must be 1
        for (int j = 0; j < pshpHDLaneLinkObj->nParts; ++j) {
            for (int k = 0; k < pshpHDLaneLinkObj->nVertices; ++k) {
                double dLon = pshpHDLaneLinkObj->padfX[k];
                double dLat = pshpHDLaneLinkObj->padfY[k];
                double dAlt = pshpHDLaneLinkObj->padfZ[k];
                if (std::isnan(dLon)) {
                    dLon = 0;
                }
                if (std::isnan(dLat)) {
                    dLat = 0;
                }
                if (std::isnan(dAlt)) {
                    dAlt = 0;
                }
                hlLane.vctvdGeoLink.push_back(std::vector<double>{dLon, dLat, dAlt});
            }
        }

        // insert the start and end node if not exist in the egolink
        // if (ptStart != Point() && ptStart.dLon != Point(hlLane.vctvdGeoLink.at(0)).dLon && ptStart.dLat != Point(hlLane.vctvdGeoLink.at(0)).dLat) {
        //     hlLane.vctvdGeoLink.insert(hlLane.vctvdGeoLink.begin(), hlLane.lnStartNode.vctdGeoNode);
        // }
        // if (ptEnd != Point() && ptEnd.dLon != Point(hlLane.vctvdGeoLink.at(hlLane.vctvdGeoLink.size() - 1)).dLon && ptEnd.dLat != Point(hlLane.vctvdGeoLink.at(hlLane.vctvdGeoLink.size() - 1)).dLat) {
        //     hlLane.vctvdGeoLink.insert(hlLane.vctvdGeoLink.end(), hlLane.lnEndNode.vctdGeoNode);
        // }

        if (mapIdVctObjArrow.find(hlLane.liId) != mapIdVctObjArrow.end()) {
            hlLane.vctarArrow = mapIdVctObjArrow.at(hlLane.liId);
        }
        if (mapLaneIdVctText.find(hlLane.liId) != mapLaneIdVctText.end()) {
            hlLane.vcttxText = mapLaneIdVctText.at(hlLane.liId);
        }
        if (mapLaneIdVctSymbol.find(hlLane.liId) != mapLaneIdVctSymbol.end()) {
            hlLane.vctsbSymbol = mapLaneIdVctSymbol.at(hlLane.liId);
        }

        if (mapLaneIdVctTrafficLight.find(hlLane.liId) != mapLaneIdVctTrafficLight.end()) {
            hlLane.vcttlTrafficLight = mapLaneIdVctTrafficLight.at(hlLane.liId);
        }

        if (mapIdVctHdLaneAdas.find(hlLane.liId) != mapIdVctHdLaneAdas.end()) {
            hlLane.vctlaLaneAdas = mapIdVctHdLaneAdas.at(hlLane.liId);
        }

        mapOutIdHdLink[lRoadId].vcthlLane.push_back(hlLane);

        for (int m = 0; m < mapOutIdHdLink[lRoadId].vctheEdge.size(); m++) {
            const HdEdge &heEdge = mapOutIdHdLink[lRoadId].vctheEdge[m];
            if (mapOutIdHdLink[lRoadId].vctheEdge[m].lId == hlLane.lRightEdgeId || mapOutIdHdLink[lRoadId].vctheEdge[m].lId == hlLane.lLeftEdgeId) {
                double angleTmp1 = jf::PointsAngle(hlLane.vctvdGeoLink[0], hlLane.vctvdGeoLink[1]);
                double angleTmp2 = jf::PointsAngle(mapOutIdHdLink[lRoadId].vctheEdge[m].vctvdGeoLink[0], mapOutIdHdLink[lRoadId].vctheEdge[m].vctvdGeoLink[1]);

                double dAngleSub = jf::AngleSub(angleTmp1, angleTmp2);
                if (dAngleSub > 90.0) {
                    reverse(mapOutIdHdLink[lRoadId].vctheEdge[m].vctvdGeoLink.begin(), mapOutIdHdLink[lRoadId].vctheEdge[m].vctvdGeoLink.end());
                    HdEdgeNode enSwap = mapOutIdHdLink[lRoadId].vctheEdge[m].enStartNode;
                    mapOutIdHdLink[lRoadId].vctheEdge[m].enStartNode = mapOutIdHdLink[lRoadId].vctheEdge[m].enEndNode;
                    mapOutIdHdLink[lRoadId].vctheEdge[m].enEndNode = enSwap;
                }
            }
        }

        SHPDestroyObject(pshpHDLaneLinkObj);
    }

    DBFClose(dbhHandle);
    SHPClose(shhHandle);
}

void MapParser::MakeSdData(const std::map<JfDataId, HdLink> &mapIdHdLink, MapIdNode &mapOutIdNode, MapIdWay &mapOutIdWay) {
    for (auto iter = mapIdHdLink.begin(); iter != mapIdHdLink.end(); ++iter) {
        BaseWay bwWay = {};
        bwWay.id = iter->first;
        bwWay.level = iter->second.nRank;
        bwWay.direction = iter->second.nDirection;

        int i = 0;
        for (std::vector<double> vctPoint : iter->second.vctvdGeoLink) {
            SdNode snNode = {};
            snNode.id_p = SdNodeId{Point(vctPoint)};
            // stNode.p = vctPoint;
            snNode.speed_limit_big = iter->second.nSpeedLimit;
            snNode.speed_limit_small = iter->second.nSpeedLimit;
            snNode.level = bwWay.level;
            // stNode.direction = stWay.direction;

            bwWay.nodes.push_back(snNode.id_p);

            mapOutIdNode[snNode.id_p] = snNode;
        }

        mapOutIdWay[bwWay.id] = bwWay;
    }
}

void MapParser::MakeHdLink(const std::map<JfDataId, HdLink> &mapIdHdLink, HdJson &jsnOutResult) {
    std::map<HdLinkId, HdLink> mapIdLink = {};
    // 预处理: for PLanes and NLanes
    // 确定所有LaneNode点的前后连接的所有的lane
    typedef LaneConnection LaneNodeConnection;
    std::map<JfDataId, LaneNodeConnection> mapLaneNodeIdConnection = {};
    for (auto iter = mapIdHdLink.begin(); iter != mapIdHdLink.end(); ++iter) {
        for (HdLane hlLane : iter->second.vcthlLane) {
            if (hlLane.nDirection == 2) {  // Lane方向与矢量方向相同 （矢量方向：GeoLink一系列坐标点方向、Lane的开始节点和结束节点方向）
                mapLaneNodeIdConnection[hlLane.lnStartNode.lId].vctNextLaneIds.push_back(hlLane.liId.lValue);
                mapLaneNodeIdConnection[hlLane.lnEndNode.lId].vctPreLaneIds.push_back(hlLane.liId.lValue);
            } else if (hlLane.nDirection == 3) {  // Lane方向与矢量方向相反
                mapLaneNodeIdConnection[hlLane.lnStartNode.lId].vctPreLaneIds.push_back(hlLane.liId.lValue);
                mapLaneNodeIdConnection[hlLane.lnEndNode.lId].vctNextLaneIds.push_back(hlLane.liId.lValue);
            } else if (hlLane.nDirection == 1) {  //双向车道
                mapLaneNodeIdConnection[hlLane.lnStartNode.lId].vctPreLaneIds.push_back(hlLane.liId.lValue);
                mapLaneNodeIdConnection[hlLane.lnEndNode.lId].vctNextLaneIds.push_back(hlLane.liId.lValue);
                mapLaneNodeIdConnection[hlLane.lnStartNode.lId].vctNextLaneIds.push_back(hlLane.liId.lValue);
                mapLaneNodeIdConnection[hlLane.lnEndNode.lId].vctPreLaneIds.push_back(hlLane.liId.lValue);
            } else {
                std::cout << "====ERROR=====车道" << hlLane.liId << "的驾驶方向未确定" << std::endl;
                while (1)
                    ;
            }
        }
    }
    // 确定所有Lane之间的前后关系
    std::map<HdLaneId, LaneConnection> mapLaneIdConnection = {};
    for (auto iter = mapLaneNodeIdConnection.begin(); iter != mapLaneNodeIdConnection.end(); ++iter) {
        // 针对LaneNode后面的所有Lane，将LaneNode前面的所有Lane加入到他们的PreLane中去
        for (HdLaneId lNextLaneId : iter->second.vctNextLaneIds) {
            for (HdLaneId lPreLaneId : iter->second.vctPreLaneIds) {
                mapLaneIdConnection[lNextLaneId].vctPreLaneIds.push_back(lPreLaneId);
            }
        }
        // 针对LaneNode前面的所有Lane，将LaneNode后面的所有Lane加入到他们的NextLane中去
        for (HdLaneId lPreLaneId : iter->second.vctPreLaneIds) {
            for (HdLaneId lNextLaneId : iter->second.vctNextLaneIds) {
                mapLaneIdConnection[lPreLaneId].vctNextLaneIds.push_back(lNextLaneId);
            }
        }
    }

    // 先生成除了PreLinks和NxtLinks之外的数据
    for (auto iter = mapIdHdLink.begin(); iter != mapIdHdLink.end(); ++iter) {
        HdLink hlLink = iter->second;

        if (iter->second.vcthlLane.size() <= 0) {
            // jf_log_info("[MapParser::MakehdLink]: map error no lanes link : {}", iter->first);
            continue;
        }
        if (iter->second.vctvdGeoLink.size() <= 0) {
            // jf_log_info("[MapParser::MakehdLink]: map error no geo link : {}", iter->first);
            continue;
        }
        std::vector<TileId> vctlTIds = {};
        GetTids(iter->second.vctvdGeoLink, vctlTIds);
        hlLink.liId = HdLinkId{iter->first, vctlTIds};

        SortHdEdges(hlLink, hlLink.vctheEdge);
        ConvertHdLanes(iter->second, mapLaneIdConnection, hlLink.vcthlLane);

        mapIdLink[hlLink.liId] = hlLink;
    }

    // 再生成PLinks和NLinks的数据
    ConvertPNLinkIds(mapIdHdLink, mapIdLink);

    jsnOutResult.links = mapIdLink;
}

void MapParser::SortHdEdges(const HdLink &hlLink, std::vector<HdEdge> &vcthlOutEdges) {
    // 将数据按照edge_num的顺序添加到vcthlSeqEdges中
    std::vector<HdEdge> vcthlSeqEdges = {};
    for (size_t i = 1; i <= hlLink.vctheEdge.size(); i++) {
        for (auto heEdge : hlLink.vctheEdge) {
            if (heEdge.nNum == -i) {
                vcthlSeqEdges.push_back(heEdge);
            }
        }
    }
    for (size_t i = 1; i <= hlLink.vctheEdge.size(); i++) {
        for (auto heEdge : hlLink.vctheEdge) {
            if (heEdge.nNum == i) {
                vcthlSeqEdges.push_back(heEdge);
            }
        }
    }

    assert(hlLink.vctheEdge.size() == vcthlSeqEdges.size());
    vcthlOutEdges = vcthlSeqEdges;

    return;
}

/***
 * 生成Link属性值中的lane数组vcthlLane
 * @param hlLink
 * @param mapLaneIdConnection
 * @param vcthlOutLanes
 */
void MapParser::ConvertHdLanes(const HdLink &hlLink, const std::map<HdLaneId, LaneConnection> &mapLaneIdConnection, std::vector<HdLane> &vcthlOutLanes) {
    std::vector<HdLane> vcthlTempLanes = {};
    for (HdLane hlLane : hlLink.vcthlLane) {
        HdLane hlTempLane = hlLane;
        static const int sc_nLaneDirection_TwoWay = 1;
        static const int sc_nLaneDirection_Forward = 2;
        static const int sc_nLaneDirection_Reverse = 3;
        if (mapLaneIdConnection.find(hlLane.liId.lValue) != mapLaneIdConnection.end()) {
            hlTempLane.vctliPreLaneId = mapLaneIdConnection.at(hlLane.liId.lValue).vctPreLaneIds;
            hlTempLane.vctliNxtLaneId = mapLaneIdConnection.at(hlLane.liId.lValue).vctNextLaneIds;
        }
        vcthlTempLanes.push_back(hlTempLane);
    }
    /**按照Lane的nSeqNum值大小，从小到大进行排序*/
    sort(vcthlTempLanes.begin(), vcthlTempLanes.end(), [](HdLane hlLane1, HdLane hlLane2) {
        int nSeqNum1 = hlLane1.nSeqNum;
        int nSeqNum2 = hlLane2.nSeqNum;
        return nSeqNum1 < nSeqNum2;
    });
    vcthlOutLanes = vcthlTempLanes;
    return;
}

/**
 * 生成RoadLink的 联通关系数据
 * @param mapIdRoad  map<JfDataId, HdLink> RoadLink的ID和RoadLink对象键值对
 * @param mapIdLink
 */
void MapParser::ConvertPNLinkIds(const std::map<JfDataId, HdLink> &mapIdRoad, std::map<HdLinkId, HdLink> &mapIdLink) {
    struct Link {
        std::vector<JfDataId> vctStartRoadIds;
        std::vector<JfDataId> vctEndRoadIds;
    };

    std::map<JfDataId, HdLinkId> mapIdLinkId = {};
    // 先遍历整个mapIdLink，生成一个以hdLinkId的id为key，以相关连的hdLinkId为值的map
    for (auto iter = mapIdLink.begin(); iter != mapIdLink.end(); ++iter) {
        mapIdLinkId[iter->first.lValue] = iter->first;
    }

    // 定义一个如下结构
    // RoadId A ->JunctionId->RoadId B
    // --------->行进方向--------->
    // 由此知道，Road A的下一个节点是Road B
    std::map<JfDataId, Link> mapJIdLinks = {};

    static const int sc_nRoadDirection_TwoWay = 1;
    static const int sc_nRoadDirection_Forward = 2;
    static const int sc_nRoadDirection_Reverse = 3;

    // 再遍历整个mapIdRoad，生成一个以JunctionId为key，以相关连的RoadId为值的map
    for (auto iter = mapIdRoad.begin(); iter != mapIdRoad.end(); ++iter) {
        if (iter->second.vcthlLane.size() <= 0) {
            // jf_log_info("[MapParser::ConvertToNLinks] map error no lanes link : {}", iter->first);
            continue;
        }

        switch (iter->second.nDirection) {
            case sc_nRoadDirection_TwoWay:
                /* 双向通行 */
                mapJIdLinks[iter->second.jcStartJunc.lId].vctStartRoadIds.push_back(iter->first);
                mapJIdLinks[iter->second.jcEndJunc.lId].vctEndRoadIds.push_back(iter->first);
                mapJIdLinks[iter->second.jcStartJunc.lId].vctEndRoadIds.push_back(iter->first);
                mapJIdLinks[iter->second.jcEndJunc.lId].vctStartRoadIds.push_back(iter->first);
                break;

            case sc_nRoadDirection_Forward:
                /* 与矢量方向相同 */
                mapJIdLinks[iter->second.jcStartJunc.lId].vctStartRoadIds.push_back(iter->first);
                mapJIdLinks[iter->second.jcEndJunc.lId].vctEndRoadIds.push_back(iter->first);
                break;
            case sc_nRoadDirection_Reverse:
                /* 与矢量方向相反 */
                mapJIdLinks[iter->second.jcStartJunc.lId].vctEndRoadIds.push_back(iter->first);
                mapJIdLinks[iter->second.jcEndJunc.lId].vctStartRoadIds.push_back(iter->first);
                break;
            default:
                /* 双向禁行, 或者未调查 */
                break;
        }
    }

    for (auto iter = mapJIdLinks.begin(); iter != mapJIdLinks.end(); ++iter) {
        for (auto nextId : iter->second.vctStartRoadIds) {
            for (auto endId : iter->second.vctEndRoadIds) {
                // 自己的下一条不能是自己
                if (mapIdLink[mapIdLinkId[nextId]].liId.lValue != mapIdLinkId[endId].lValue) {
                    mapIdLink[mapIdLinkId[nextId]].vctliPreLinkId.push_back(mapIdLinkId[endId]);
                }
            }
        }
    }

    for (auto iter = mapJIdLinks.begin(); iter != mapJIdLinks.end(); ++iter) {
        for (auto preId : iter->second.vctEndRoadIds) {
            for (auto startId : iter->second.vctStartRoadIds) {
                // 自己的上一条不能是自己
                if (mapIdLink[mapIdLinkId[preId]].liId.lValue != mapIdLinkId[startId].lValue) {
                    mapIdLink[mapIdLinkId[preId]].vctliNxtLinkId.push_back(mapIdLinkId[startId]);
                }
            }
        }
    }
}

void MapParser::GetTids(const std::vector<std::vector<double>> &vctvdGeoLink, std::vector<TileId> &vctOutTids) {
    std::set<TileId> setTids = {};
    for (const std::vector<double> &vctdGeoLink : vctvdGeoLink) {
        TileId tid = P2TId(Point(vctdGeoLink));
        setTids.insert(tid);
    }

    vctOutTids = Utils::Set2Vector(setTids);

    return;
}

// void MapParser::insertFeatures(const std::string &strPath, HdJson &data) {
//     std::string strFeature = strPath + c_cFeature_json;
//     std::map<hdMarkerId, std::vector<double>> marks;
//     FileSys fs;
//     std::string is;
//     if (true == fs.read(strFeature, is)) {
//         ajson::load_from_buff(marks, is.c_str());
//         for (auto &lk : data.links) {
//             for (hdettmk &vcthmMarks : lk.second.entity_marks) {
//                 vcthmMarks.feature = marks[vcthmMarks.lValue];
//             }
//         }
//     }
// }

int MapParser::Factorial(int n) {
    // 计算阶乘
    int nResult = 1;
    for (size_t i = 2; i <= n; i++) {
        nResult *= i;
    }

    return nResult;
}

}  // namespace jf