From 9f14bb4ef2f9184b983a8b1a8a3b69f6e9a225b6 Mon Sep 17 00:00:00 2001
From: Sergi Hernandez Juan <shernand@iri.upc.edu>
Date: Fri, 11 Dec 2020 17:58:27 +0100
Subject: [PATCH] Added the functions to link nodes and lanes: not working yet.
 TO DO: add the functions to link road segments.

---
 include/opendrive_lane.h         |   6 +
 include/opendrive_link.h         |   1 +
 include/opendrive_object.h       |   2 +-
 include/opendrive_road_node.h    |   2 +-
 include/opendrive_road_segment.h |   4 +
 include/opendrive_signal.h       |   2 +-
 src/opendrive_lane.cpp           | 155 +++++++++++++++++++++--
 src/opendrive_link.cpp           |   5 +
 src/opendrive_object.cpp         |  38 +++---
 src/opendrive_road_node.cpp      |  24 +++-
 src/opendrive_road_segment.cpp   | 210 ++++++++++++++++++++++++-------
 src/opendrive_signal.cpp         |  20 +--
 12 files changed, 375 insertions(+), 94 deletions(-)

diff --git a/include/opendrive_lane.h b/include/opendrive_lane.h
index 48b7381..33e2120 100644
--- a/include/opendrive_lane.h
+++ b/include/opendrive_lane.h
@@ -15,6 +15,10 @@ class COpendriveLane
   friend class COpendriveRoadSegment;
   private:
     std::vector<COpendriveRoadNode *> nodes;
+    COpendriveLane *left_lane;
+    opendrive_mark_t left_mark;
+    COpendriveLane *right_lane;
+    opendrive_mark_t right_mark;
     COpendriveRoadSegment *segment;
     double scale_factor;
     double resolution;
@@ -23,6 +27,8 @@ class COpendriveLane
     double offset;
     int id;
   protected:
+    void link_left_lane(COpendriveLane *lane);
+    void link_right_lane(COpendriveLane *lane);
     void add_node(COpendriveRoadNode *node);
     void set_resolution(double res);
     void set_scale_factor(double scale);
diff --git a/include/opendrive_link.h b/include/opendrive_link.h
index bd4d7ca..5f5478b 100644
--- a/include/opendrive_link.h
+++ b/include/opendrive_link.h
@@ -25,6 +25,7 @@ class COpendriveLink
     void set_road_mark(opendrive_mark_t mark);
     void set_resolution(double res);
     void set_scale_factor(double scale);
+    void generate(void);
   public:
     COpendriveLink();
     COpendriveLink(const COpendriveLink &object);
diff --git a/include/opendrive_object.h b/include/opendrive_object.h
index 7db50f2..cb8bb16 100644
--- a/include/opendrive_object.h
+++ b/include/opendrive_object.h
@@ -50,7 +50,7 @@ class COpendriveObject
   public:
     COpendriveObject();
     COpendriveObject(const COpendriveObject& object);
-    void load(std::unique_ptr<objects::object_type> &object_info);
+    void load(objects::object_type &object_info);
     TOpendriveTrackPoint get_pose(void) const;
     std::string get_type(void) const;
     std::string get_name(void) const;
diff --git a/include/opendrive_road_node.h b/include/opendrive_road_node.h
index e7d704d..0e87653 100644
--- a/include/opendrive_road_node.h
+++ b/include/opendrive_road_node.h
@@ -19,7 +19,7 @@ class COpendriveRoadNode
     COpendriveLane *lane;
     COpendriveGeometry *geometry;
   protected:
-    unsigned int add_link(COpendriveRoadNode *node);
+    void add_link(COpendriveRoadNode *node,opendrive_mark_t mark);
     void set_resolution(double res);
     void set_scale_factor(double scale);
   public:
diff --git a/include/opendrive_road_segment.h b/include/opendrive_road_segment.h
index 3824abd..b428549 100644
--- a/include/opendrive_road_segment.h
+++ b/include/opendrive_road_segment.h
@@ -28,10 +28,14 @@ class COpendriveRoadSegment
     std::string name;
     unsigned int id;
   protected:
+    void free(void);
     void set_resolution(double res);
     void set_scale_factor(double scale);
     void set_min_road_length(double length);
     void update_references(std::map<COpendriveRoadSegment *,COpendriveRoadSegment *> refs);
+    void add_lanes(lanes::laneSection_type &lane_section);
+    void add_nodes(OpenDRIVE::road_type &road_info);
+    void link_lanes(lanes::laneSection_type &lane_section);
   public:
     COpendriveRoadSegment();
     COpendriveRoadSegment(const COpendriveRoadSegment &object);
diff --git a/include/opendrive_signal.h b/include/opendrive_signal.h
index 2048dbe..3f16293 100644
--- a/include/opendrive_signal.h
+++ b/include/opendrive_signal.h
@@ -20,7 +20,7 @@ class COpendriveSignal
     COpendriveSignal();
     COpendriveSignal(const COpendriveSignal &object);
     COpendriveSignal(int id, double s, double t, double heading, std::string type, std::string sub_type, int value, std::string text, bool reverse = false);
-    void load(std::unique_ptr<signals::signal_type> &signal_info);
+    void load(signals::signal_type &signal_info);
     int get_id(void) const;
     TOpendriveTrackPoint get_pose(void) const;
     void get_type(std::string &type, std::string &sub_type) const;
diff --git a/src/opendrive_lane.cpp b/src/opendrive_lane.cpp
index 735204d..6720c1e 100644
--- a/src/opendrive_lane.cpp
+++ b/src/opendrive_lane.cpp
@@ -4,6 +4,10 @@
 COpendriveLane::COpendriveLane()
 {
   this->nodes.clear();
+  this->left_lane=NULL;
+  this->left_mark=OD_MARK_NONE;
+  this->right_lane=NULL;
+  this->right_mark=OD_MARK_NONE;
   this->segment=NULL;
   this->resolution=DEFAULT_RESOLUTION;
   this->scale_factor=DEFAULT_SCALE_FACTOR;
@@ -23,6 +27,10 @@ COpendriveLane::COpendriveLane(const COpendriveLane &object)
     node=new COpendriveRoadNode(*object.nodes[i]);
     this->nodes.push_back(node);
   }
+  this->left_lane=object.left_lane;
+  this->left_mark=object.left_mark;
+  this->right_lane=object.right_lane;
+  this->right_mark=object.right_mark;
   this->segment=object.segment;
   this->resolution=object.resolution;
   this->scale_factor=object.scale_factor;
@@ -32,6 +40,40 @@ COpendriveLane::COpendriveLane(const COpendriveLane &object)
   this->id=object.id;
 }
 
+void COpendriveLane::link_left_lane(COpendriveLane *lane)
+{
+  if(lane!=NULL)
+  {
+    if(this->get_num_nodes()!=lane->get_num_nodes())
+      throw CException(_HERE_,"Impossible to link lanes because they have different number of nodes");
+    for(unsigned int i=1;i<this->get_num_nodes();i++)
+    {
+      this->nodes[i]->add_link(lane->nodes[i-1],this->left_mark);
+      lane->nodes[i]->add_link(this->nodes[i-1],this->left_mark);
+    } 
+    this->left_lane=lane;
+  }
+  else
+    this->left_lane=NULL;
+}
+
+void COpendriveLane::link_right_lane(COpendriveLane *lane)
+{
+  if(lane!=NULL)
+  {
+    if(this->get_num_nodes()!=lane->get_num_nodes())
+      throw CException(_HERE_,"Impossible to link lanes because they have different number of nodes");
+    for(unsigned int i=1;i<this->get_num_nodes();i++)
+    {
+      this->nodes[i]->add_link(lane->nodes[i-1],this->right_mark);
+      lane->nodes[i]->add_link(this->nodes[i-1],this->right_mark);
+    } 
+    this->right_lane=lane;
+  }
+  else
+    this->right_lane=NULL;
+}
+
 void COpendriveLane::add_node(COpendriveRoadNode *node)
 {
   for(unsigned int i=0;i<this->nodes.size();i++)
@@ -39,6 +81,9 @@ void COpendriveLane::add_node(COpendriveRoadNode *node)
       return;
   // add the new node
   this->nodes.push_back(node);
+  // link the new node with the previous one in the current lane, if any
+  if(this->nodes.size()>1)
+    this->nodes[this->nodes.size()-1]->add_link(node,OD_MARK_NONE);
 }
 
 void COpendriveLane::set_resolution(double res)
@@ -70,6 +115,7 @@ void COpendriveLane::update_references(std::map<COpendriveRoadSegment *,COpendri
 void COpendriveLane::load(const right::lane_type &lane_info,COpendriveRoadSegment *segment)
 {
   std::stringstream error;
+  opendrive_mark_t mark;
 
   for(unsigned int i=0;i<this->nodes.size();i++)
   {
@@ -77,31 +123,56 @@ void COpendriveLane::load(const right::lane_type &lane_info,COpendriveRoadSegmen
     this->nodes[i]=NULL;
   }
   this->nodes.clear();
+  this->left_lane=NULL;
+  this->left_mark=OD_MARK_NONE;
+  this->right_lane=NULL;
+  this->right_mark=OD_MARK_NONE;
   this->id=lane_info.id().get();
   // import lane width
-  if(lane_info.width().size()<1)
+  if(lane_info.width().size()!=1)
   {
-    error << "No width record present for lane " << this->id;
-    throw CException(_HERE_,error.str());
-  }
-  else if(lane_info.width().size()>1)
-  {
-    error << "More than one width record present for lane " << this->id;
+    error << "Only one width record supported for lane " << this->id;
     throw CException(_HERE_,error.str());
   }
   this->width=lane_info.width().begin()->a().get();
   // import lane speed
-  if(lane_info.speed().size()<1)
+  if(lane_info.speed().size()!=1)
   {
-    error << "No speed record present for lane " << this->id;
+    error << "Only one speed record supported for lane " << this->id;
     throw CException(_HERE_,error.str());
   }
-  else if(lane_info.speed().size()>1)
+  this->speed=lane_info.speed().begin()->max().get();
+  //lane mark
+  if(lane_info.roadMark().size()!=1)
   {
-    error << "More than one speed record present for lane " << this->id;
+    error << "Only one road mark supported for lane " << this->id;
     throw CException(_HERE_,error.str());
   }
-  this->speed=lane_info.speed().begin()->max().get();
+  if(lane_info.roadMark().begin()->type().present())
+  {
+    if(lane_info.roadMark().begin()->type().get()=="none")
+      mark=OD_MARK_NONE;
+    else if(lane_info.roadMark().begin()->type().get()=="solid")
+      mark=OD_MARK_SOLID;
+    else if(lane_info.roadMark().begin()->type().get()=="broken")
+      mark=OD_MARK_BROKEN;
+    else if(lane_info.roadMark().begin()->type().get()=="solid_solid")
+      mark=OD_MARK_SOLID_SOLID;
+    else if(lane_info.roadMark().begin()->type().get()=="solid_broken")
+      mark=OD_MARK_SOLID_BROKEN;
+    else if(lane_info.roadMark().begin()->type().get()=="broken_solid")
+      mark=OD_MARK_BROKEN_SOLID;
+    else if(lane_info.roadMark().begin()->type().get()=="broken_broken")
+      mark=OD_MARK_BROKEN_BROKEN;
+    else
+      mark=OD_MARK_NONE;
+  }
+  else
+    mark=OD_MARK_NONE;
+  if(this->id<0)//right lanes
+    this->right_mark=mark;
+  else
+    this->left_mark=mark;
 
   this->segment=segment;
 }
@@ -172,6 +243,62 @@ std::ostream& operator<<(std::ostream& out, COpendriveLane &lane)
     out << "    Parent road segment: " << lane.segment->get_name() << std::endl;
   else 
     out << "    No parent segment" << std::endl;
+  if(lane.left_lane!=NULL)
+    out << "    No left lane (" << std::endl;
+  else
+    out << "    Left lane " << lane.get_id() << " (" << std::endl;
+  switch(lane.left_mark)
+  {
+    case OD_MARK_NONE:
+      out << "no mark)" << std::endl;
+      break;
+    case OD_MARK_SOLID:
+      out << "solid)" << std::endl;
+      break;
+    case OD_MARK_BROKEN:
+      out << "broken)" << std::endl;
+      break;
+    case OD_MARK_SOLID_SOLID:
+      out << "solid solid)" << std::endl;
+      break;
+    case OD_MARK_SOLID_BROKEN:
+      out << "solid broken)" << std::endl;
+      break;
+    case OD_MARK_BROKEN_SOLID:
+      out << "broken solid)" << std::endl;
+      break;
+    case OD_MARK_BROKEN_BROKEN:
+      out << "broken broken)" << std::endl;
+      break;
+  }
+  if(lane.right_lane!=NULL)
+    out << "    No right lane (" << std::endl;
+  else
+    out << "    Right lane " << lane.get_id() << " (" << std::endl;
+  switch(lane.right_mark)
+  {
+    case OD_MARK_NONE:
+      out << "no mark)" << std::endl;
+      break;
+    case OD_MARK_SOLID:
+      out << "solid)" << std::endl;
+      break;
+    case OD_MARK_BROKEN:
+      out << "broken)" << std::endl;
+      break;
+    case OD_MARK_SOLID_SOLID:
+      out << "solid solid)" << std::endl;
+      break;
+    case OD_MARK_SOLID_BROKEN:
+      out << "solid broken)" << std::endl;
+      break;
+    case OD_MARK_BROKEN_SOLID:
+      out << "broken solid)" << std::endl;
+      break;
+    case OD_MARK_BROKEN_BROKEN:
+      out << "broken broken)" << std::endl;
+      break;
+  }
   out << "    Number of nodes: " << lane.nodes.size() << std::endl;
   for(unsigned int i=0;i<lane.nodes.size();i++)
     out << *lane.nodes[i] << std::endl;
@@ -187,6 +314,10 @@ COpendriveLane::~COpendriveLane()
     this->nodes[i]=NULL;
   }
   this->nodes.clear();
+  this->left_lane=NULL;
+  this->left_mark=OD_MARK_NONE;
+  this->right_lane=NULL;
+  this->right_mark=OD_MARK_NONE;
   this->segment=NULL;
   this->resolution=DEFAULT_RESOLUTION;
   this->scale_factor=DEFAULT_SCALE_FACTOR;
diff --git a/src/opendrive_link.cpp b/src/opendrive_link.cpp
index 724da05..05c4e89 100644
--- a/src/opendrive_link.cpp
+++ b/src/opendrive_link.cpp
@@ -35,6 +35,11 @@ void COpendriveLink::set_scale_factor(double scale)
 
 }
 
+void COpendriveLink::generate(void)
+{
+
+}
+
 const COpendriveRoadNode &COpendriveLink::get_prev(void) const
 {
 
diff --git a/src/opendrive_object.cpp b/src/opendrive_object.cpp
index 2cff044..9b6f71f 100644
--- a/src/opendrive_object.cpp
+++ b/src/opendrive_object.cpp
@@ -43,41 +43,41 @@ COpendriveObject::COpendriveObject(const COpendriveObject& object)
   }
 }
 
-void COpendriveObject::load(std::unique_ptr<objects::object_type> &object_info)
+void COpendriveObject::load(objects::object_type &object_info)
 {
   double u,v;
   unsigned int i;
-  std::stringstream ss(object_info->id().get());
+  std::stringstream ss(object_info.id().get());
   outline::cornerRoad_iterator corner_road_it;
   outline::cornerLocal_iterator corner_local_it;
 
   ss >> this->id;
-  this->pose.s = (object_info->s().present() ? object_info->s().get() : 0.0);
-  this->pose.t = (object_info->t().present() ? object_info->t().get() : 0.0);
-  this->pose.heading = (object_info->hdg().present() ? object_info->hdg().get() : 0.0);
-  this->type = (object_info->type().present() ? object_info->type().get() : "");
-  this->name = (object_info->name().present() ? object_info->name().get() : "");
-  if(object_info->length().present() && object_info->width().present() && object_info->height().present())
+  this->pose.s = (object_info.s().present() ? object_info.s().get() : 0.0);
+  this->pose.t = (object_info.t().present() ? object_info.t().get() : 0.0);
+  this->pose.heading = (object_info.hdg().present() ? object_info.hdg().get() : 0.0);
+  this->type = (object_info.type().present() ? object_info.type().get() : "");
+  this->name = (object_info.name().present() ? object_info.name().get() : "");
+  if(object_info.length().present() && object_info.width().present() && object_info.height().present())
   {
     this->object_type=OD_BOX;
-    this->object.box.length=object_info->length().get();
-    this->object.box.width=object_info->width().get();
-    this->object.box.height=object_info->height().get();
+    this->object.box.length=object_info.length().get();
+    this->object.box.width=object_info.width().get();
+    this->object.box.height=object_info.height().get();
   }
-  else if(object_info->height().present() && object_info->radius().present())
+  else if(object_info.height().present() && object_info.radius().present())
   {
     this->object_type=OD_CYLINDER;
-    this->object.cylinder.radius=object_info->radius().get();
-    this->object.cylinder.height=object_info->height().get();
+    this->object.cylinder.radius=object_info.radius().get();
+    this->object.cylinder.height=object_info.height().get();
   }
-  else if(object_info->outline().present())
+  else if(object_info.outline().present())
   {
     this->object_type=OD_POLYGON;
     this->object.polygon.num_vertices=0;
     // absolute track coordinates
-    if(object_info->outline().get().cornerRoad().size()>0)// absolute track coordinates
+    if(object_info.outline().get().cornerRoad().size()>0)// absolute track coordinates
     {
-      for(i=0,corner_road_it=object_info->outline().get().cornerRoad().begin();i<OD_MAX_VERTICES && corner_road_it != object_info->outline().get().cornerRoad().end(); ++corner_road_it,++i)
+      for(i=0,corner_road_it=object_info.outline().get().cornerRoad().begin();i<OD_MAX_VERTICES && corner_road_it != object_info.outline().get().cornerRoad().end(); ++corner_road_it,++i)
       {
         this->object.polygon.vertices[i].s=(corner_road_it->s().present() ? corner_road_it->s().get() : 0.0);
         this->object.polygon.vertices[i].t=(corner_road_it->t().present() ? corner_road_it->t().get() : 0.0);
@@ -85,9 +85,9 @@ void COpendriveObject::load(std::unique_ptr<objects::object_type> &object_info)
         this->object.polygon.num_vertices++;
       }
     }
-    else if(object_info->outline().get().cornerLocal().size()>0)// local coordinates with respect to the object anchor point
+    else if(object_info.outline().get().cornerLocal().size()>0)// local coordinates with respect to the object anchor point
     {
-      for(i=0,corner_local_it=object_info->outline().get().cornerLocal().begin();i<OD_MAX_VERTICES && corner_local_it != object_info->outline().get().cornerLocal().end(); ++corner_local_it,++i)
+      for(i=0,corner_local_it=object_info.outline().get().cornerLocal().begin();i<OD_MAX_VERTICES && corner_local_it != object_info.outline().get().cornerLocal().end(); ++corner_local_it,++i)
       {
         u=(corner_local_it->u().present() ? corner_local_it->u().get() : 0.0);
         v=(corner_local_it->v().present() ? corner_local_it->v().get() : 0.0);
diff --git a/src/opendrive_road_node.cpp b/src/opendrive_road_node.cpp
index 8a17bfc..61c05b4 100644
--- a/src/opendrive_road_node.cpp
+++ b/src/opendrive_road_node.cpp
@@ -31,9 +31,29 @@ COpendriveRoadNode::COpendriveRoadNode(const COpendriveRoadNode &object)
   }
 }
 
-unsigned int COpendriveRoadNode::add_link(COpendriveRoadNode *parent)
+void COpendriveRoadNode::add_link(COpendriveRoadNode *node,opendrive_mark_t mark)
 {
-  return -1;
+  COpendriveLink *new_link;
+
+  for(unsigned int i=0;i<this->links.size();i++)
+  {
+    if(this->links[i]->prev==this && this->links[i]->next==node)
+      throw CException(_HERE_,"Link already present in the source node");
+  }
+  for(unsigned int i=0;i<node->links.size();i++)
+  {
+    if(node->links[i]->prev==this && node->links[i]->next==node)
+      throw CException(_HERE_,"Link already present in the target node");
+  }
+  new_link=new COpendriveLink();
+  new_link->set_prev(this);
+  new_link->set_next(node);
+  new_link->set_resolution(this->resolution);
+  new_link->set_scale_factor(this->scale_factor);
+  new_link->set_road_mark(mark);
+  new_link->generate();
+  this->links.push_back(new_link);
+  node->links.push_back(new_link);
 }
 
 void COpendriveRoadNode::set_resolution(double res)
diff --git a/src/opendrive_road_segment.cpp b/src/opendrive_road_segment.cpp
index d1ecdcf..1b77e8e 100644
--- a/src/opendrive_road_segment.cpp
+++ b/src/opendrive_road_segment.cpp
@@ -55,6 +55,32 @@ COpendriveRoadSegment::COpendriveRoadSegment(const COpendriveRoadSegment &object
   this->min_road_length=object.min_road_length;
 }
 
+void COpendriveRoadSegment::free(void)
+{
+  for(unsigned int i=-this->num_right_lanes;i<=this->num_left_lanes && i!=0;i++)
+  {
+    delete this->lanes[i];
+    this->lanes[i]=NULL;
+  }
+  this->lanes.clear();
+  this->num_left_lanes=0;
+  this->num_right_lanes=0;
+  for(unsigned int i=0;i<this->signals.size();i++)
+  {
+    delete this->signals[i];
+    this->signals[i]=NULL;
+  }
+  this->signals.clear();
+  for(unsigned int i=0;i<this->objects.size();i++)
+  {
+    delete this->objects[i];
+    this->objects[i]=NULL;
+  }
+  this->objects.clear();
+  this->next.clear();
+  this->prev.clear();
+}
+
 void COpendriveRoadSegment::set_resolution(double res)
 {
   std::map<int,COpendriveLane *>::const_iterator lane_it;
@@ -91,32 +117,16 @@ void COpendriveRoadSegment::update_references(std::map<COpendriveRoadSegment *,C
     this->lanes[i]->update_references(refs);
 }
 
-void COpendriveRoadSegment::load(OpenDRIVE::road_type &road_info)
+void COpendriveRoadSegment::add_lanes(lanes::laneSection_type &lane_section)
 {
-  std::map<int,COpendriveLane *>::const_iterator lane_it;
-  lanes::laneSection_iterator lane_section;
   right::lane_iterator r_lane_it;
   left::lane_iterator l_lane_it;
-  planView::geometry_iterator geom_it;
   COpendriveLane *new_lane;
-  COpendriveRoadNode *new_node;
-  double lane_offset;
-
-  this->name=road_info.name().get();
-  this->id=std::stoi(road_info.id().get());
-  // only one lane section is supported
-  if(road_info.lanes().laneSection().size()<1)
-    throw CException(_HERE_,"No lane sections defined for road "+road_info.id().get());
-  else if(road_info.lanes().laneSection().size()>1)
-    throw CException(_HERE_,"Road "+road_info.id().get()+" has more than one lane section");
-  else
-    lane_section=road_info.lanes().laneSection().begin();
 
   // right lanes
-  this->num_right_lanes=0;
-  if(lane_section->right().present())
+  if(lane_section.right().present())
   {
-    for(r_lane_it=lane_section->right()->lane().begin();r_lane_it!=lane_section->right()->lane().end();r_lane_it++)
+    for(r_lane_it=lane_section.right()->lane().begin();r_lane_it!=lane_section.right()->lane().end();r_lane_it++)
     {
       try{
         new_lane=new COpendriveLane();
@@ -131,10 +141,9 @@ void COpendriveRoadSegment::load(OpenDRIVE::road_type &road_info)
     }
   }
   // left lanes
-  this->num_left_lanes=0;
-  if(lane_section->left().present())
+  if(lane_section.left().present())
   {
-    for(l_lane_it=lane_section->left()->lane().begin();l_lane_it!=lane_section->left()->lane().end();l_lane_it++)
+    for(l_lane_it=lane_section.left()->lane().begin();l_lane_it!=lane_section.left()->lane().end();l_lane_it++)
     {
       try{
         new_lane=new COpendriveLane();
@@ -148,7 +157,15 @@ void COpendriveRoadSegment::load(OpenDRIVE::road_type &road_info)
       }
     }
   }
-  // add road nodes
+}
+
+void COpendriveRoadSegment::add_nodes(OpenDRIVE::road_type &road_info)
+{
+  std::map<int,COpendriveLane *>::const_iterator lane_it;
+  planView::geometry_iterator geom_it;
+  COpendriveRoadNode *new_node;
+  double lane_offset;
+
   try{
     for(geom_it=road_info.planView().geometry().begin(); geom_it!=road_info.planView().geometry().end(); ++geom_it)
     {
@@ -166,6 +183,10 @@ void COpendriveRoadSegment::load(OpenDRIVE::road_type &road_info)
           lane_offset-=this->lanes[i]->get_width();
         }
       }
+    }
+    for(geom_it=road_info.planView().geometry().end(); geom_it!=road_info.planView().geometry().begin();)
+    {
+      geom_it--;
       lane_offset=0.0;
       for(unsigned int i=1;i<=this->num_left_lanes;i++)
       {
@@ -189,6 +210,122 @@ void COpendriveRoadSegment::load(OpenDRIVE::road_type &road_info)
   }
 }
 
+void COpendriveRoadSegment::link_lanes(lanes::laneSection_type &lane_section)
+{
+  opendrive_mark_t center_mark;
+  center::lane_type center_lane;
+
+  if(lane_section.center().lane().present())
+  {
+    center_lane=lane_section.center().lane().get();
+    if(center_lane.roadMark().begin()->type().present())
+    {
+      if(center_lane.roadMark().begin()->type().get()=="none")
+        center_mark=OD_MARK_NONE;
+      else if(center_lane.roadMark().begin()->type().get()=="solid")
+        center_mark=OD_MARK_SOLID;
+      else if(center_lane.roadMark().begin()->type().get()=="broken")
+        center_mark=OD_MARK_BROKEN;
+      else if(center_lane.roadMark().begin()->type().get()=="solid_solid")
+        center_mark=OD_MARK_SOLID_SOLID;
+      else if(center_lane.roadMark().begin()->type().get()=="solid_broken")
+        center_mark=OD_MARK_SOLID_BROKEN;
+      else if(center_lane.roadMark().begin()->type().get()=="broken_solid")
+        center_mark=OD_MARK_BROKEN_SOLID;
+      else if(center_lane.roadMark().begin()->type().get()=="broken_broken")
+        center_mark=OD_MARK_BROKEN_BROKEN;
+      else
+        center_mark=OD_MARK_NONE;
+    }
+    else
+      center_mark=OD_MARK_NONE;
+  }
+  for(unsigned int i=-this->num_right_lanes;i<0;i++)
+  {
+    if(i==-this->num_right_lanes)// right most lane
+    {
+      if((i+1)==0)//center lane
+      {
+        if(this->lanes.find(i+2)!=this->lanes.end())
+          this->lanes[i]->link_left_lane(this->lanes[i+2]);
+        this->lanes[i]->left_mark=center_mark;
+      }
+      else
+      {
+        if(this->lanes.find(i+1)!=this->lanes.end())
+          this->lanes[i]->link_left_lane(this->lanes[i+1]);
+        this->lanes[i]->left_mark=this->lanes[i+1]->right_mark;
+      }
+    }
+  }
+  for(unsigned int i=this->num_left_lanes;i>0;i--)
+  {
+    if(i==this->num_left_lanes)// right most lane
+    {
+      if((i-1)==0)//center lane
+      {
+        if(this->lanes.find(i-2)!=this->lanes.end())
+          this->lanes[i]->link_right_lane(this->lanes[i-2]);
+        this->lanes[i]->right_mark=center_mark;
+      }
+      else
+      {
+        if(this->lanes.find(i-1)!=this->lanes.end())
+          this->lanes[i]->link_left_lane(this->lanes[i-1]);
+        this->lanes[i]->right_mark=this->lanes[i+1]->left_mark;
+      }
+    }
+  }
+}
+
+void COpendriveRoadSegment::load(OpenDRIVE::road_type &road_info)
+{
+  std::map<int,COpendriveLane *>::const_iterator lane_it;
+  signals::signal_iterator signal_it;
+  objects::object_iterator object_it;
+  lanes::laneSection_iterator lane_section;
+  COpendriveSignal *new_signal;
+  COpendriveObject *new_object;
+
+  this->free();
+  this->name=road_info.name().get();
+  this->id=std::stoi(road_info.id().get());
+  // only one lane section is supported
+  if(road_info.lanes().laneSection().size()<1)
+    throw CException(_HERE_,"No lane sections defined for road "+road_info.id().get());
+  else if(road_info.lanes().laneSection().size()>1)
+    throw CException(_HERE_,"Road "+road_info.id().get()+" has more than one lane section");
+  else
+    lane_section=road_info.lanes().laneSection().begin();
+
+  // add lanes
+  this->add_lanes(*lane_section);
+  // add road nodes
+  this->add_nodes(road_info);
+  // link lanes
+  this->link_lanes(*lane_section);
+  // add road signals
+  if(road_info.signals().present())
+  {
+    for(signal_it=road_info.signals().get().signal().begin();signal_it!=road_info.signals().get().signal().end();++signal_it)
+    {
+      new_signal=new COpendriveSignal();
+      new_signal->load(*signal_it);
+      this->signals.push_back(new_signal);
+    }
+  }
+  // add road objects
+  if(road_info.objects().present())
+  {
+    for(object_it=road_info.objects().get().object().begin();object_it!=road_info.objects().get().object().end();++object_it)
+    {
+      new_object=new COpendriveObject();
+      new_object->load(*object_it);
+      this->objects.push_back(new_object);
+    }
+  }
+}
+
 std::string COpendriveRoadSegment::get_name(void) const
 {
   return this->name;
@@ -280,21 +417,19 @@ void COpendriveRoadSegment::operator=(const COpendriveRoadSegment &object)
   COpendriveObject *new_object;
   std::map<int,COpendriveLane *>::const_iterator lane_it;
 
+  this->free();
   this->name=object.name;
   this->id=object.id;
-  this->lanes.clear();
   for(lane_it=object.lanes.begin();lane_it!=object.lanes.end();++lane_it)
   {
     new_lane=new COpendriveLane(*lane_it->second);
     this->lanes[lane_it->first]=new_lane;
   }
-  this->signals.clear();
   for(unsigned int i=0;i<object.signals.size();i++)
   {
     new_signal=new COpendriveSignal(*object.signals[i]);
     this->signals.push_back(new_signal);
   }
-  this->objects.clear();
   for(unsigned int i=0;i<object.objects.size();i++)
   {
     new_object=new COpendriveObject(*object.objects[i]);
@@ -338,30 +473,9 @@ std::ostream& operator<<(std::ostream& out, COpendriveRoadSegment &segment)
 
 COpendriveRoadSegment::~COpendriveRoadSegment()
 {
+  this->free();
   this->name="";
   this->id=-1;
-  for(unsigned int i=-this->num_right_lanes;i<=this->num_left_lanes && i!=0;i++)
-  {
-    delete this->lanes[i];
-    this->lanes[i]=NULL;
-  }
-  this->lanes.clear();
-  this->num_left_lanes=0;
-  this->num_right_lanes=0;
-  for(unsigned int i=0;i<this->signals.size();i++)
-  {
-    delete this->signals[i];
-    this->signals[i]=NULL;
-  }
-  this->signals.clear();
-  for(unsigned int i=0;i<this->objects.size();i++)
-  {
-    delete this->objects[i];
-    this->objects[i]=NULL;
-  }
-  this->objects.clear();
-  this->next.clear();
-  this->prev.clear();
   this->resolution=DEFAULT_RESOLUTION;
   this->scale_factor=DEFAULT_SCALE_FACTOR;
   this->min_road_length=DEFAULT_MIN_ROAD_LENGTH;
diff --git a/src/opendrive_signal.cpp b/src/opendrive_signal.cpp
index 7e7d744..2083166 100644
--- a/src/opendrive_signal.cpp
+++ b/src/opendrive_signal.cpp
@@ -37,19 +37,19 @@ COpendriveSignal::COpendriveSignal(int id, double s, double t, double heading, s
   this->text=text;
 }
 
-void COpendriveSignal::load(std::unique_ptr<signals::signal_type> &signal_info)
+void COpendriveSignal::load(signals::signal_type &signal_info)
 {
-  std::stringstream ss(signal_info->id().get());
+  std::stringstream ss(signal_info.id().get());
   ss >> this->id;
-  this->pose.s = (signal_info->s().present() ? signal_info->s().get() : 0.0);
-  this->pose.t = (signal_info->t().present() ? signal_info->t().get() : 0.0);
-  this->pose.heading = (signal_info->hOffset().present() ? signal_info->hOffset().get() : 0.0);
-  this->type = (signal_info->type().present() ? signal_info->type().get() : "");
-  this->sub_type = (signal_info->subtype().present() ? signal_info->subtype().get() : "");
-  this->value = (signal_info->value().present() ? signal_info->value().get() : 0.0);
-  this->text = (signal_info->text().present() ? signal_info->text().get() : "");
+  this->pose.s = (signal_info.s().present() ? signal_info.s().get() : 0.0);
+  this->pose.t = (signal_info.t().present() ? signal_info.t().get() : 0.0);
+  this->pose.heading = (signal_info.hOffset().present() ? signal_info.hOffset().get() : 0.0);
+  this->type = (signal_info.type().present() ? signal_info.type().get() : "");
+  this->sub_type = (signal_info.subtype().present() ? signal_info.subtype().get() : "");
+  this->value = (signal_info.value().present() ? signal_info.value().get() : 0.0);
+  this->text = (signal_info.text().present() ? signal_info.text().get() : "");
   bool reverse = false;
-  if (signal_info->orientation().present() && signal_info->orientation().get() == orientation::cxx_1)
+  if (signal_info.orientation().present() && signal_info.orientation().get() == orientation::cxx_1)
     reverse = true;
   this->pose.heading = normalize_angle(this->pose.heading + (reverse ? M_PI : 0.0));
 }
-- 
GitLab