#ifndef _JFXMAP_HDTYPES_H_
#define _JFXMAP_HDTYPES_H_

#include <assert.h>

#include <iostream>
#include <map>
#include <sstream>
#include <vector>

#include "CoordSys.h"
#include "MapConfig.h"
#include "Serialize.h"
#include "Singleton.h"
#include "Utils.h"
#include "World.h"

namespace jf {
struct HdNode {
    HdNode() : lId(0) {}

    JfDataId lId;
    std::vector<double> vctdGeoNode;
};

enum DirectionValue {
    NotInvestigated = 0,  // 未调查
    TwoWayPass,           // 双向通行
    SameToVectorization,  // 与矢量化方向相同
    DiffToVectorization,  // 与矢量化方向相反
    TwoWayNoPass,         // 双向禁行
};

enum ArrowValue {
    UTurnLeft = 'A',       // 左掉头
    TurnLeft = 'B',        // 左转
    GoStraight = 'C',      // 直行
    TurnRight = 'D',       // 右转:
    UTurnRight = 'E',      // 右掉头 :
    TurnMergeLeft = 'G',   // 左弯或向左合流
    TurnMergeRight = 'H',  // 右弯或向右合流
};

template <typename InNodeIdType, typename InNodeDataType, typename InSerializeDataType>
class Tile;

template <typename InNodeIdType, typename InNodeDataType, typename TileType>
class World;
class Save;

/**
 * 车道边界线跨越方向
 */
static const int sc_nCrossDirec_Unknown = 0;      //未调查
static const int sc_nCrossDirec_Unable = 1;       //不可以跨越
static const int sc_nCrossDirec_BidirecAble = 2;  //双方向跨越
static const int sc_nCrossDirec_LeftAble = 3;     //左方向跨越
static const int sc_nCrossDirec_RightAble = 4;    //右方向跨越

static const char sc_cArrow_LeftUTurn = 'A';
static const char sc_cArrow_LeftTurn = 'B';
static const char sc_cArrow_Straight = 'C';
static const char sc_cArrow_RightTurn = 'D';
static const char sc_cArrow_RightUTurn = 'E';
static const char sc_cArrow_LeftConf = 'G';
static const char sc_cArrow_RightConf = 'H';

/**车道中心线节点**/
struct HdLaneNode : HdNode {};

/**地面箭头**/
struct ObjArrow {
    ObjArrow() : lId(0), nColor(0), strType("") {}

    enum ColorValue {
        NotInvestigated = 0,  // 未调查
        White = 1,            // 白色
        Yellow = 2,           // 黄色
        Ohters = 99,          // 其它
    };

    JfDataId lId;
    int nColor;           // Color
    std::string strType;  // Arrow_type

    std::vector<std::vector<double>> vctvdGeoArea;
};

/**交通信号灯***/
struct ObjTrafficLight {
    ObjTrafficLight() : lId(0), dHeading(0.0), nType(0), strDir(""), nArray(0), nCount(0) {}

    JfDataId lId;
    //        std::vector<HdLaneId> vctlLaneId;
    double dHeading;
    int nType;
    std::string strDir;
    int nArray;
    int nCount;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**地面文字***/
struct ObjText {
    ObjText() : lId(0), nColor(0), strText("") {}

    enum ColorValue {
        NotInvestigated = 0,  // 未调查
        White = 1,            // 白色
        Yellow = 2,           // 黄色
        Red = 3,              // 红色
        Colorfull = 4,        // 彩色
        Ohters = 99,          // 其它
    };

    JfDataId lId;
    int nColor;           // Color
    std::string strText;  // Text

    std::vector<std::vector<double>> vctvdGeoArea;
};

/**地面符号**/
struct ObjSymbol {
    ObjSymbol(JfDataId lId, const std::vector<HdLaneId> &vctlLaneId, int color) : lId(lId), vctlLaneId(vctlLaneId), color(color) {}
    ObjSymbol() {}
    enum ColorValue {
        NotInvestigated = 0,  // 未调查
        White = 1,            // 白色
        Yellow = 2,           // 黄色
        Red = 3,              // 红色
        Colorfull = 4,        // 彩色
        Ohters = 99,          // 其他
    };
    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    int color;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**车道高级属性**/
struct HdLaneAdas {
    HdLaneAdas() : nSeqNum(0), dLon(0.0), dLat(0.0), dOutCurvature(0.0), dOutRoll(0.0), dOutPitch(0.0), dOutAzimuth(0.0), dOffset(0.0) {}

    int nSeqNum;
    double dLon;
    double dLat;
    double dOutCurvature;
    double dOutRoll;
    double dOutPitch;
    double dOutAzimuth;
    double dOffset;
};

/**车道属性***/
struct HdLane {
    HdLane() : lLeftEdgeId(0), lRightEdgeId(0), nSeqNum(0), nDirection(0), nType(0), strArrows(""), nWidth(0), nMaxSpeed(0), nMinSpeed(0) {}

    enum TypeValue {
        NotInvestigated = 0,         // 未调查
        NormalLane = 1,              // 普通车道
        EnterLane = 2,               // 入口车道
        ExitLane = 3,                // 出口车道
        ConnectLane = 4,             // 连接车道
        EmergencyLane = 5,           // 应急车道
        StopLane = 6,                // 停车道
        EmergencyStopLane = 7,       // 紧急停车道
        AcceleratingLane = 8,        // 加速车道
        DeceleratingLane = 9,        // 减速车道
        HazardLane = 10,             // 避险车道
        JunctionLane = 11,           // 路口车道
        TollStationLane = 12,        // 收费站车道
        CheckpointLane = 13,         // 检查站车道
        UTurnLane = 14,              // 掉头车道
        BusLane = 15,                // 公交车道
        TidalLane = 16,              // 潮汐(可变) 车道
        LocomotiveLane = 17,         // 机车车道
        LocomotiveParkingArea = 18,  // 机车停车区
        HOVHighLoadLane = 19,        // HOV 高承载车道
        NonMotorizedLane = 30,       // 非机动车道
        Sidewalk = 40,               // 人行道
        Ohters = 99,                 // 其它车道
    };

    HdLaneId liId;           // LaneId
    HdLaneNode lnStartNode;  // SL_Node
    HdLaneNode lnEndNode;    // EL_NodeId
    JfDataId lLeftEdgeId;    // L_EdgeId
    JfDataId lRightEdgeId;   // R_EdgeId
    int nSeqNum;             // Lane_no
    int nDirection;          // Direction
    int nType;               // Lane_type;
    std::string strArrows;   // Arrow
    int nWidth;              // Lane_width
    int nMaxSpeed;           // Max speed
    int nMinSpeed;           // Min speed

    std::vector<std::vector<double>> vctvdGeoLink;

    std::vector<ObjArrow> vctarArrow;                //地面箭头
    std::vector<ObjTrafficLight> vcttlTrafficLight;  //交通信号灯
    std::vector<ObjText> vcttxText;                  //地面文字
    std::vector<ObjSymbol> vctsbSymbol;              //地面符号

    std::vector<HdLaneAdas> vctlaLaneAdas;

    std::vector<HdLaneId> vctliPreLaneId;  // 和该车道相连接的所有车道ID的集合：前面的车道集合
    std::vector<HdLaneId> vctliNxtLaneId;  // 和该车道相连接的所有车道ID的集合：后面的车道集合
};
inline bool operator==(const HdLane &left, const HdLane &right) { return left.liId == right.liId; }
inline bool operator!=(const HdLane &left, const HdLane &right) { return !(left == right); }

struct HdEdgeNode : HdNode {};

/**车道标线信息**/
struct HdLaneMark {
    HdLaneMark() : lId(0), nNum(0), nType(0), nColor(0), nWidth(0) {}

    enum TypeValue {
        NotInvestigated = 0,            // 未调查
        SolidLine = 1,                  // 实线
        DottedLine = 2,                 // 虚线
        ShortThickDottedLine = 3,       // 短粗虚线
        VariableLaneMarking = 4,        // 可变车道标线
        DecelerationPromptMarking = 5,  // 减速提示标线
    };

    enum ColorValue {
        // NotInvestigated = 0,  // 未调查
        White = 1,    // 白色
        Yellow = 2,   // 黄色
        Red = 3,      // 红色
        Blue = 4,     // 蓝色
        Green = 5,    // 绿色
        Others = 99,  // 其他
    };

    JfDataId lId;
    int nNum;    // Mark_no
    int nType;   // Mark_type
    int nColor;  // Mark_color
    int nWidth;  // Mark_width

    std::vector<std::vector<double>> vctvdGeoArea;
};

struct HdEdge {
    HdEdge() : lId(0), nNum(0), nType(0), nCross(0) {}

    enum TypeValue {
        NotInvestigated = 0,             // 未调查
        NoMarkingsDistinguishEdges = 1,  // 无标线无可区分边
        Marking = 2,                     // 标线
        Guardrail = 4,                   // 护栏
        Wall = 5,                        // 墙
        PaveEdge = 6,                    // 道路面铺设边缘
        Shoulder = 7,                    // 路牙, 路肩
        Greenbelt = 8,                   // 绿化带
        Others = 99,                     // 其它
    };

    enum CrossValue {
        // NotInvestigated = 0,  // 未调查
        Unable = 1,       // 无法跨越
        BidirecAble = 2,  // 双方向跨越
        LeftAble = 3,     // 向左跨越
        RightAble = 4,    // 向右跨越
    };

    JfDataId lId;            // lId
    HdEdgeNode enStartNode;  // SE_Node
    HdEdgeNode enEndNode;    // EE_Node
    int nNum;                // Edge_no
    int nType;               // Edge_type
    int nCross;              // Edge_cross
    int nMarkCount;          // Mark_count

    std::vector<std::vector<double>> vctvdGeoLink;

    std::vector<HdLaneMark> vcthmMark;
};

struct RoadJunction : HdNode {};

struct RoadEdgeNode : HdNode {};

struct RoadEdge {
    RoadEdge() : lId(0), nType(0), nColor(0) {}

    enum REdgeTypeValue {
        NotInvestigated = 0,  // 未调查
        VirtualLine = 1,      // 虚拟线
        Marking = 2,          // 标线
        Guardrail = 4,        // 护栏
        Wall = 5,             // 墙
        PaveEdge = 6,         // 道路面铺设边缘
        Shoulder = 7,         // 路牙, 路肩
        Greenbelt = 8,        // 绿化带
        Others = 99,          // 其它
    };

    enum REdgeColorValue {
        // NotInvestigated = 0,  // 未调查
        White = 1,    // 白色
        Yellow = 2,   // 黄色
        Red = 3,      // 红色
        Ohters = 99,  // 其它
    };

    JfDataId lId;
    RoadEdgeNode enStartNode;
    RoadEdgeNode enEndNode;
    int nType;
    int nColor;

    std::vector<std::vector<double>> vctvdGeoLink;
};

/**路口面****/
struct RoadCrossArea {
    RoadCrossArea() : lId(0) {}

    JfDataId lId;

    std::vector<std::vector<double>> vctvdGeoArea;
};

/**交通牌照**/
struct ObjTrafficSign {
    ObjTrafficSign() : lId(0), nShape(0), nType(0), nType1(0), nType2(0), strText("") {}

    enum ShapeValue {
        NotInvestigated = 0,  // 未调查
        Rectangle = 1,        // 1:长方形
        Round = 2,            // 圆形
        Triangle = 3,         // 三角形
        Rhombus = 4,          // 菱形
        Others = 99,          // 其它
    };

    enum TypeValue {
        // NotInvestigated = 0,  // 未调查
        Normal = 1,    // 普通交通信息牌
        Variable = 2,  // 可变交通信息牌
    };

    enum Type1Value {
        // NotInvestigated = 0,  // 未调查
        Warning = 2,       // 警告
        Ban = 3,           // 禁令
        Instructions = 4,  // 指示
        Guide = 5,         // 指引
        Information = 6,   // 告知
        Tourist = 7,       // 旅游区
    };

    JfDataId lId;
    int nShape;           // Shape
    int nType;            // Sign_type
    int nType1;           // Type 1
    int nType2;           // Type 2
    std::string strText;  // Sign_text

    std::vector<std::vector<double>> vctvdGeoArea;
};

/**杆状物**/
struct ObjPole {
    ObjPole() : lId(0), height(0), poleType(0) {}
    enum PoleTypeValue {
        NotInvestigated = 0,  //未调查
        LightPole = 1,        //灯杆
        LabelPole = 2,        //标牌杆
        OtherPole = 99        //其他杆
    };

    JfDataId lId;
    int height;    //高度（毫米）
    int poleType;  //对象细分类
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**停止线****/
struct ObjStopLine {
    ObjStopLine() : lId(0), nType(0), nColor(0) {}

    enum TypeValue {
        NotInvestigated = 0,        // 未调查
        StopLine = 1,               // 停止线
        ParkingYieldLine = 2,       // 停车让行线
        DecelerationYieldLine = 3,  // 减速让行线
    };

    enum ColorValue {
        // NotInvestigated = 0,  // 未调查
        White = 1,   // 白色
        Yellow = 2,  // 黄色
    };

    JfDataId lId;
    int nType;   // Type
    int nColor;  // Color

    std::vector<std::vector<double>> vctvdGeoLink;
};

/**人行横道***/
struct ObjCrossing {
    ObjCrossing() : lId(0) {}

    JfDataId lId;

    std::vector<std::vector<double>> vctvdGeoArea;
};

/**上方障碍物***/
struct ObjOverHead {
    ObjOverHead() : lId(0), height(0.0), OH_type(0) {}
    enum OverHeadTypeValue {
        NotInvestigated = 0,  //未调查
        Gantry = 1,           //龙门架
        Bridge = 2,           //天桥
        TrafficPole = 3,      //交通横杆
        Tunnel = 4,           //隧道
        Road = 5,             //上方道路
        Other = 99            //其他
    };

    JfDataId lId;
    int OH_type;    //障碍物类型
    double height;  //高度
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoLink;
};

/**禁止停车区域****/
struct ObjNoParking {
    ObjNoParking() : lId(0) {}

    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**减速带**/
struct ObjSpeedBump {
    ObjSpeedBump() : lId(0) {}
    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**停车区**/
struct ObjParking {
    ObjParking() : lId(0) {}
    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**导流区*/
struct ObjFillArea {
    ObjFillArea() : lId(0) {}
    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**消防拴*/
struct ObjHydrant {
    ObjHydrant() : lId(0) {}

    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**公交站***/
struct ObjBusStop {
    ObjBusStop() : lId(0) {}
    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    std::vector<std::vector<double>> vctvdGeoArea;
};

/**RS信号灯***/
struct ObjPoint {
    ObjPoint() : lId(0), nType(0), strMemo1(""), strMemo2(""), strMemo3(""), strMemo4("") {}

    JfDataId lId;
    std::vector<HdLaneId> vctlLaneId;
    int nType;
    std::string strMemo1;
    std::string strMemo2;
    std::string strMemo3;
    std::string strMemo4;
    std::vector<double> vctdGeoNode;
};

/***道路link**/
struct HdLink {
    HdLink() : dLength(0.0), nLaneNum(0), nDirection(0), nRank(0), nType(0), dStartAngle(0.0), strName(""), nSpeedLimit(0) {}

    enum RankValue {
        NotInvestigated = 0,     // 未调查
        Highway = 1,             //高速道路
        NationalRoad = 2,        // 国道
        ProvincialRoad = 3,      // 省道
        CountyRoad = 4,          // 县道
        CountryRoad = 5,         // 乡道
        InternalRoad = 6,        // 内部道路
        CityFast = 7,            // 城市快速
        CityMainRoad = 8,        // 城市主干道
        UrbanSecondaryRoad = 9,  // 城市次干道
        InnerCityRoad = 10,      // 城市内部路
        CityPath = 11,           // 城市小路
        Others = 99,             // 其它
    };

    enum TypeValue {
        // NotInvestigated = 0,  // 未调查
        Road = 1,           // 道路
        Bridge = 2,         // 桥梁
        Tunnel = 3,         // 隧道
        UnderElevated = 5,  // 高架下
        UrbanCanyon = 6,    // 城市峡谷
        // Others = 99,        // 其它
    };

    HdLinkId liId;                         // RoadID道路编号
    RoadJunction jcStartJunc;              // link起点
    RoadJunction jcEndJunc;                // link终点
    std::vector<RoadEdge> vctreLeftEdge;   // 左边界
    std::vector<RoadEdge> vctreRightEdge;  // 右边界
    double dLength;                        // Length
    int nLaneNum;                          // Lane_num
    int nDirection;                        // Direction
    int nRank;                             // Road_rank
    int nType;                             // Road_type
    double dStartAngle;                    // start angle
    std::string strName;                   // Name
    int nSpeedLimit;                       // Speed  限速（km/h）

    std::vector<std::vector<double>> vctvdGeoLink;  // 车道参考线

    std::vector<HdEdge> vctheEdge;  // 车道边缘线
    std::vector<HdLane> vcthlLane;  // lane

    std::vector<RoadCrossArea> vctcaCrossArea;       // 路口面
    std::vector<ObjTrafficSign> vctTrafficSign;      // 交通标牌
    std::vector<ObjPole> vctPole;                    // 杆状物
    std::vector<ObjStopLine> vctslStopLine;          // 停止线
    std::vector<ObjCrossing> vctcrCrossing;          // 人行横道
    std::vector<ObjTrafficLight> vcttlTrafficLight;  // 交通信号灯
    std::vector<ObjOverHead> vctOverHead;            // 上方障碍物
    std::vector<ObjNoParking> vctNoParking;          // 禁止停车区域
    std::vector<ObjSpeedBump> vctSpeedBump;          // 减速带
    std::vector<ObjParking> vctParking;              // 停车区域
    std::vector<ObjFillArea> vctFillArea;            // 导流区
    std::vector<ObjHydrant> vctHydrant;              // 消防栓
    std::vector<ObjBusStop> vctBusStop;              // 公交站
    std::vector<ObjPoint> vctRsuPoint;               // RSU信号灯

    std::vector<HdLinkId> vctliPreLinkId;
    std::vector<HdLinkId> vctliNxtLinkId;

    const HdLane *GetLane_DEPRECATED(const int &nLaneIndex) const {
        for (const HdLane &hlLane : vcthlLane) {
            if (nLaneIndex + 1 == hlLane.nSeqNum) {
                return &hlLane;
            }
        }
        // jf_log_error("assert false : HdTypes::GetLane_DEPRECATED {}", nLaneIndex);
        return nullptr;
    }

    // offset 左侧/右侧道路
    const HdLane *GetLaneByIdAndOffset(const HdLaneId &liId, int nOffset) const {
        const HdLane *cur = GetLaneById(liId);
        if (!cur) {
            return nullptr;
        }
        int offset_seq_num = cur->nSeqNum + nOffset;
        return GetLaneBySeqNum(offset_seq_num);
    }

    const HdLane *GetLaneBySeqNum(int seq_num) const {
        for (const HdLane &hlLane : vcthlLane) {
            if (seq_num == hlLane.nSeqNum) {
                return &hlLane;
            }
        }
        // jf_log_error("assert false : HdTypes::GetLaneById {}", liId);
        return nullptr;
    }

    const HdLane *GetLaneById(const JfDataId &liId) const {
        for (const HdLane &hlLane : vcthlLane) {
            if (liId == hlLane.liId.lValue) {
                return &hlLane;
            }
        }
        // jf_log_error("assert false : HdTypes::GetLaneById {}", liId);
        return nullptr;
    }

    const HdEdge *GetEdgeById(const JfDataId &lId) const {
        for (const HdEdge &egEdge : vctheEdge) {
            if (lId == egEdge.lId) {
                return &egEdge;
            }
        }
        // jf_log_error("assert false : HdTypes::GetEdgeById {}", lId);
        return nullptr;
    }
};

inline bool operator<(const HdLink &l, const HdLink &r) { return l.liId.lValue < r.liId.lValue; }

struct HdJson {
    std::map<HdLinkId, HdLink> links;
};

struct HdSerializeData {
    using saveType = MapConfig::hdConfig;
    Rect2D r;
    std::vector<HdLinkId> m_keys;
    std::vector<HdLink> m_values;
    std::vector<uint64_t> states;
    std::vector<std::vector<HdLinkId>> nodes;
    std::vector<std::vector<Point>> ps;
    HdSerializeData(const Rect2D &inr, const std::map<HdLinkId, HdLink> &inm, std::vector<uint64_t> instates, std::vector<std::vector<HdLinkId>> &innodes, std::vector<std::vector<Point>> &inps) : r(inr), states(instates), nodes(innodes), ps(inps) {
        for (auto &iter : inm) {
            auto &k = iter.first;
            auto &v = iter.second;
            m_keys.push_back(k);
            m_values.push_back(v);
        }
    }
    HdSerializeData() : r(Point(0, 0, 0), Point(0, 0, 0)) {}
};

typedef Save HdSave;
typedef Tile<HdLinkId, HdLink, HdSerializeData> HdTile;
struct NewHdWorld {
    static World<HdLinkId, HdLink, HdTile> *Create() { return new World<HdLinkId, HdLink, HdTile>(new HdSave); };
};
typedef Singleton<World<HdLinkId, HdLink, HdTile>, NewHdWorld> HdWorld;

};  // namespace jf

#ifndef jfxmap_serialize_override_HdNode
jfxmap_serialize(jf::HdNode, lId, vctdGeoNode);
#endif
#ifndef jfxmap_serialize_override_HdLaneNode
jfxmap_serialize(jf::HdLaneNode, lId, vctdGeoNode);
#endif
#ifndef jfxmap_serialize_override_ObjArrow
jfxmap_serialize(jf::ObjArrow, lId, nColor, strType, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjTrafficLight
jfxmap_serialize(jf::ObjTrafficLight, lId, dHeading, nType, strDir, nArray, nCount, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjText
jfxmap_serialize(jf::ObjText, lId, nColor, strText, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjSymbol
jfxmap_serialize(jf::ObjSymbol, lId, vctlLaneId, color, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_HdLaneAdas
jfxmap_serialize(jf::HdLaneAdas, nSeqNum, dLon, dLat, dOutCurvature, dOutRoll, dOutPitch, dOutAzimuth);
#endif
#ifndef jfxmap_serialize_override_HdLane
jfxmap_serialize(jf::HdLane, liId, lnStartNode, lnEndNode, lLeftEdgeId, lRightEdgeId, nSeqNum, nDirection, nType, strArrows, nWidth, nMaxSpeed, nMinSpeed, vctvdGeoLink, vctarArrow, vcttlTrafficLight, vcttxText, vctsbSymbol, vctlaLaneAdas, vctliPreLaneId,
                 vctliNxtLaneId);
#endif
#ifndef jfxmap_serialize_override_HdLaneMark
jfxmap_serialize(jf::HdLaneMark, lId, nNum, nType, nColor, nWidth, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_HdEdge
jfxmap_serialize(jf::HdEdge, lId, enStartNode, enEndNode, nNum, nType, nCross, nMarkCount, vctvdGeoLink, vcthmMark);
#endif
#ifndef jfxmap_serialize_override_HdEdgeNode
jfxmap_serialize(jf::HdEdgeNode, lId, vctdGeoNode);
#endif
#ifndef jfxmap_serialize_override_RoadJunction
jfxmap_serialize(jf::RoadJunction, lId, vctdGeoNode);
#endif
#ifndef jfxmap_serialize_override_RoadEdgeNode
jfxmap_serialize(jf::RoadEdgeNode, lId, vctdGeoNode);
#endif
#ifndef jfxmap_serialize_override_RoadEdge
jfxmap_serialize(jf::RoadEdge, lId, enStartNode, enEndNode, nType, nColor, vctvdGeoLink);
#endif
#ifndef jfxmap_serialize_override_RoadCrossArea
jfxmap_serialize(jf::RoadCrossArea, lId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjTrafficSign
jfxmap_serialize(jf::ObjTrafficSign, lId, nType, nShape, nType1, nType2, strText, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjPole
jfxmap_serialize(jf::ObjPole, lId, height, poleType, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjStopLine
jfxmap_serialize(jf::ObjStopLine, lId, nType, nColor, vctvdGeoLink);
#endif
#ifndef jfxmap_serialize_override_ObjCrossing
jfxmap_serialize(jf::ObjCrossing, lId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_HdOverHead
jfxmap_serialize(jf::ObjOverHead, lId, OH_type, height, vctlLaneId, vctvdGeoLink);
#endif
#ifndef jfxmap_serialize_override_ObjNoParking
jfxmap_serialize(jf::ObjNoParking, lId, vctlLaneId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjSpeedBump
jfxmap_serialize(jf::ObjSpeedBump, lId, vctlLaneId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjParking
jfxmap_serialize(jf::ObjParking, lId, vctlLaneId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjFillArea
jfxmap_serialize(jf::ObjFillArea, lId, vctlLaneId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjHydrant
jfxmap_serialize(jf::ObjHydrant, lId, vctlLaneId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjBusStop
jfxmap_serialize(jf::ObjBusStop, lId, vctlLaneId, vctvdGeoArea);
#endif
#ifndef jfxmap_serialize_override_ObjPoint
jfxmap_serialize(jf::ObjPoint, lId, vctlLaneId, nType, strMemo1, strMemo2, strMemo3, strMemo4, vctdGeoNode);
#endif
#ifndef jfxmap_serialize_override_HdLink
jfxmap_serialize(jf::HdLink, liId, jcStartJunc, jcEndJunc, vctreLeftEdge, vctreRightEdge, dLength, nLaneNum, nDirection, nRank, nType, dStartAngle, strName, nSpeedLimit, vctvdGeoLink, vctheEdge, vcthlLane, vctcaCrossArea, vctTrafficSign, vctPole,
                 vctslStopLine, vctcrCrossing, vcttlTrafficLight, vctOverHead, vctNoParking, vctSpeedBump, vctParking, vctFillArea, vctHydrant, vctBusStop, vctRsuPoint, vctliPreLinkId, vctliNxtLinkId);
#endif

#ifndef jfxmap_serialize_override_HdLinkId
jfxmap_serialize(jf::HdLinkId, lValue, vcttiTileIds);
#endif
#ifndef jfxmap_serialize_override_HdLaneId
jfxmap_serialize(jf::HdLaneId, lValue);
#endif
#ifndef jfxmap_serialize_override_hdjson
jfxmap_serialize(jf::HdJson, links);
#endif
#ifndef jfxmap_serialize_override_hdSerializeData
jfxmap_serialize(jf::HdSerializeData, m_keys, m_values, r, states, nodes, ps);
#endif

namespace std {
template <>  // function-template-specialization
class hash<jf::HdLaneId> {
   public:
    size_t operator()(const jf::HdLaneId &liId) const { return liId.lValue; }
};
template <>  // function-template-specialization
class hash<jf::HdLinkId> {
   public:
    size_t operator()(const jf::HdLinkId &liId) const { return liId.lValue; }
};

template <>  // function-template-specialization
class hash<jf::HdLink> {
   public:
    size_t operator()(const jf::HdLink &hlLink) const { return hlLink.liId.lValue; }
};
}  // namespace std
#endif
