public void CreateSafetyImplicitZones(ArbiterIntersection ai)
        {
            if (ai.StoppedExits.Count > 0)
            {
                foreach (ITraversableWaypoint itw in ai.AllExits.Values)
                {
                    if (itw is ArbiterWaypoint && !itw.IsStop)
                    {
                        ArbiterWaypoint aw = (ArbiterWaypoint)itw;
                        ArbiterLane al = aw.Lane;
                        LinePath.PointOnPath end = aw.Lane.LanePath().GetClosestPoint(aw.Position);

                        double dist = -30;
                        LinePath.PointOnPath begin = al.LanePath().AdvancePoint(end, ref dist);
                        if (dist != 0)
                        {
                            EditorOutput.WriteLine("safety zone too close to start of lane, setting start to start of lane: " + aw.ToString());
                            begin = al.LanePath().StartPoint;
                        }
                        ArbiterSafetyZone asz = new ArbiterSafetyZone(al, end, begin);
                        al.SafetyZones.Add(asz);
                        al.Way.Segment.RoadNetwork.DisplayObjects.Add(asz);
                        al.Way.Segment.RoadNetwork.ArbiterSafetyZones.Add(asz);

                        if (aw != null && aw.IsExit == true)
                        {
                            asz.isExit = true;
                            asz.Exit = aw;
                        }

                        // add to display
                        this.rd.displayObjects.Add(asz);
                    }
                }
            }
        }
        /// <summary>
        /// Generates the xySegments into segments and inputs them into the input road network
        /// </summary>
        /// <param name="arn"></param>
        /// <returns></returns>
        public ArbiterRoadNetwork GenerateSegments(ArbiterRoadNetwork arn)
        {
            foreach (SimpleSegment ss in segments)
            {
                // seg
                ArbiterSegmentId asi = new ArbiterSegmentId(int.Parse(ss.Id));
                ArbiterSegment   asg = new ArbiterSegment(asi);
                arn.ArbiterSegments.Add(asi, asg);
                asg.RoadNetwork = arn;
                asg.SpeedLimits = new ArbiterSpeedLimit();
                asg.SpeedLimits.MaximumSpeed = 13.4112;                 // 30mph max speed

                // way1
                ArbiterWayId awi1 = new ArbiterWayId(1, asi);
                ArbiterWay   aw1  = new ArbiterWay(awi1);
                aw1.Segment = asg;
                asg.Ways.Add(awi1, aw1);
                asg.Way1 = aw1;

                // way2
                ArbiterWayId awi2 = new ArbiterWayId(2, asi);
                ArbiterWay   aw2  = new ArbiterWay(awi2);
                aw2.Segment = asg;
                asg.Ways.Add(awi2, aw2);
                asg.Way2 = aw2;

                // make lanes
                foreach (SimpleLane sl in ss.Lanes)
                {
                    // lane
                    ArbiterLaneId ali;
                    ArbiterLane   al;

                    // get way of lane id
                    if (ss.Way1Lanes.Contains(sl))
                    {
                        ali = new ArbiterLaneId(GenerationTools.GetId(sl.Id)[1], awi1);
                        al  = new ArbiterLane(ali);
                        aw1.Lanes.Add(ali, al);
                        al.Way = aw1;
                    }
                    else
                    {
                        ali = new ArbiterLaneId(GenerationTools.GetId(sl.Id)[1], awi2);
                        al  = new ArbiterLane(ali);
                        aw2.Lanes.Add(ali, al);
                        al.Way = aw2;
                    }

                    // add to display
                    arn.DisplayObjects.Add(al);

                    // width
                    al.Width = sl.LaneWidth == 0 ? TahoeParams.T * 2.0 : sl.LaneWidth * 0.3048;

                    if (sl.LaneWidth == 0)
                    {
                        Console.WriteLine("lane: " + ali.ToString() + " contains no lane width, setting to 4m");
                    }

                    // lane boundaries
                    al.BoundaryLeft  = this.GenerateLaneBoundary(sl.LeftBound);
                    al.BoundaryRight = this.GenerateLaneBoundary(sl.RightBound);

                    // add lane to seg
                    asg.Lanes.Add(ali, al);

                    // waypoints
                    List <ArbiterWaypoint> waypointList = new List <ArbiterWaypoint>();

                    // generate waypoints
                    foreach (SimpleWaypoint sw in sl.Waypoints)
                    {
                        // waypoint
                        ArbiterWaypointId awi = new ArbiterWaypointId(GenerationTools.GetId(sw.ID)[2], ali);
                        ArbiterWaypoint   aw  = new ArbiterWaypoint(sw.Position, awi);
                        aw.Lane = al;

                        // stop
                        if (sl.Stops.Contains(sw.ID))
                        {
                            aw.IsStop = true;
                        }

                        // checkpoint
                        foreach (SimpleCheckpoint sc in sl.Checkpoints)
                        {
                            if (sw.ID == sc.WaypointId)
                            {
                                aw.IsCheckpoint = true;
                                aw.CheckpointId = int.Parse(sc.CheckpointId);
                                arn.Checkpoints.Add(aw.CheckpointId, aw);
                            }
                        }

                        // add
                        asg.Waypoints.Add(awi, aw);
                        arn.ArbiterWaypoints.Add(awi, aw);
                        al.Waypoints.Add(awi, aw);
                        waypointList.Add(aw);
                        arn.DisplayObjects.Add(aw);
                        arn.LegacyWaypointLookup.Add(sw.ID, aw);
                    }

                    al.WaypointList = waypointList;

                    // lane partitions
                    List <ArbiterLanePartition> alps = new List <ArbiterLanePartition>();
                    al.Partitions = alps;

                    // generate lane partitions
                    for (int i = 0; i < waypointList.Count - 1; i++)
                    {
                        // create lane partition
                        ArbiterLanePartitionId alpi = new ArbiterLanePartitionId(waypointList[i].WaypointId, waypointList[i + 1].WaypointId, ali);
                        ArbiterLanePartition   alp  = new ArbiterLanePartition(alpi, waypointList[i], waypointList[i + 1], asg);
                        alp.Lane = al;
                        waypointList[i].NextPartition         = alp;
                        waypointList[i + 1].PreviousPartition = alp;
                        alps.Add(alp);
                        arn.DisplayObjects.Add(alp);

                        // crete initial user partition
                        ArbiterUserPartitionId      aupi = new ArbiterUserPartitionId(alp.PartitionId, waypointList[i].WaypointId, waypointList[i + 1].WaypointId);
                        ArbiterUserPartition        aup  = new ArbiterUserPartition(aupi, alp, waypointList[i], waypointList[i + 1]);
                        List <ArbiterUserPartition> aups = new List <ArbiterUserPartition>();
                        aups.Add(aup);
                        alp.UserPartitions = aups;
                        alp.SetDefaultSparsePolygon();
                        arn.DisplayObjects.Add(aup);
                    }

                    // path segments of lane
                    List <IPathSegment> ips          = new List <IPathSegment>();
                    List <Coordinates>  pathSegments = new List <Coordinates>();
                    pathSegments.Add(alps[0].Initial.Position);

                    // loop
                    foreach (ArbiterLanePartition alPar in alps)
                    {
                        ips.Add(new LinePathSegment(alPar.Initial.Position, alPar.Final.Position));
                        // make new segment
                        pathSegments.Add(alPar.Final.Position);
                    }

                    // generate lane partition path
                    LinePath partitionPath = new LinePath(pathSegments);
                    al.SetLanePath(partitionPath);
                    al.PartitionPath = new Path(ips, CoordinateMode.AbsoluteProjected);

                    // safeto zones
                    foreach (ArbiterWaypoint aw in al.Waypoints.Values)
                    {
                        if (aw.IsStop)
                        {
                            LinePath.PointOnPath end = al.GetClosestPoint(aw.Position);
                            double dist = -30;
                            LinePath.PointOnPath begin = al.LanePath().AdvancePoint(end, ref dist);
                            if (dist != 0)
                            {
                                begin = al.LanePath().StartPoint;
                            }
                            ArbiterSafetyZone asz = new ArbiterSafetyZone(al, end, begin);
                            asz.isExit = true;
                            asz.Exit   = aw;
                            al.SafetyZones.Add(asz);
                            arn.DisplayObjects.Add(asz);
                            arn.ArbiterSafetyZones.Add(asz);
                        }
                    }
                }
            }

            return(arn);
        }
        /// <summary>
        /// When mouse clicked
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseClick(MouseEventArgs e)
        {
            #region Left

            if (e.Button == MouseButtons.Left)
            {
                if (this.CurrentEditorTool is RulerTool)
                {
                    RulerTool ruler = (RulerTool)this.CurrentEditorTool;

                    if (ruler.Initial == null)
                    {
                        ruler.Initial = transform.GetWorldPoint(new PointF(e.X, e.Y));

                        if (this.SecondaryEditorTool != null && this.SecondaryEditorTool is PointAnalysisTool)
                        {
                            PointAnalysisTool pat = ((PointAnalysisTool)this.SecondaryEditorTool);

                            pat.Save = new List<Coordinates>();
                            pat.Save.Add(ruler.Initial.Value);
                        }
                    }
                    else if (ruler.Current != null)
                    {
                        ruler.Initial = null;
                        ruler.Current = null;

                        if (this.SecondaryEditorTool != null && this.SecondaryEditorTool is PointAnalysisTool)
                        {
                            PointAnalysisTool pat = ((PointAnalysisTool)this.SecondaryEditorTool);

                            pat.Save = null;
                        }
                    }
                }
                else if (this.CurrentEditorTool is SparseTool)
                {
                    ((SparseTool)this.CurrentEditorTool).Click(transform.GetWorldPoint(new PointF(e.X, e.Y)));
                }
                else if (this.CurrentEditorTool is AngleMeasureTool)
                {
                    AngleMeasureTool amt = (AngleMeasureTool)this.CurrentEditorTool;

                    if (amt.SetP1 == false)
                    {
                        amt.VSetP1(transform.GetWorldPoint(new PointF(e.X, e.Y)), this.SecondaryEditorTool);
                    }
                    else if (amt.SetP2 == false)
                    {
                        amt.VSetP2(transform.GetWorldPoint(new PointF(e.X, e.Y)), this.SecondaryEditorTool);
                    }
                    else if (amt.SetP3 == false)
                    {
                        amt.VSetP3(this.SecondaryEditorTool);
                    }
                }
                else if (this.CurrentEditorTool is WaypointAdjustmentTool)
                {
                    if (((WaypointAdjustmentTool)this.CurrentEditorTool).CheckInMove)
                    {
                        this.CurrentEditorTool = new WaypointAdjustmentTool(this.transform);
                    }
                    else
                    {
                        // create display object filter for waypoints
                        DisplayObjectFilter dof = delegate(IDisplayObject target)
                        {
                            // check if target is network object
                            if (target is IGenericWaypoint && target is IDisplayObject)
                                return true;
                            else
                                return false;
                        };

                        // perform hit test
                        HitTestResult htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), dof);

                        // check for validity
                        if (htr.Hit)
                        {
                            // set adjust
                            ((WaypointAdjustmentTool)this.CurrentEditorTool).SetWaypoint(htr.DisplayObject, ((IGenericWaypoint)htr.DisplayObject).Position);
                        }
                    }
                }
                else if (this.CurrentEditorTool is IntersectionPulloutTool)
                {
                    IntersectionPulloutTool tool = (IntersectionPulloutTool)this.CurrentEditorTool;

                    // get key current
                    KeyStateInfo shiftKey = KeyboardInfo.GetKeyState(Keys.ShiftKey);

                    if (!shiftKey.IsPressed)
                    {
                        if (tool.Mode == InterToolboxMode.SafetyZone)
                        {
                            // create display object filter for waypoints
                            DisplayObjectFilter dof = delegate(IDisplayObject target)
                            {
                                // check if target is network object
                                if (target is ArbiterLane)
                                    return true;
                                else
                                    return false;
                            };

                            // perform hit test
                            HitTestResult htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), dof);

                            // check for validity
                            if (htr.Hit)
                            {
                                // set undo
                                tool.ed.SaveUndoPoint();

                                // get lane
                                ArbiterLane al = (ArbiterLane)htr.DisplayObject;

                                // get point on lane
                                LinePath.PointOnPath end = al.GetClosestPoint(transform.GetWorldPoint(new PointF(e.X, e.Y)));

                                ArbiterWaypoint aw = al.GetClosestWaypoint(al.LanePath().GetPoint(end), 5);

                                if (aw != null && aw.IsExit == true)
                                {
                                    end = al.GetClosestPoint(aw.Position);
                                }

                                double dist = -30;
                                LinePath.PointOnPath begin = al.LanePath().AdvancePoint(end, ref dist);
                                if (dist != 0)
                                {
                                    EditorOutput.WriteLine("safety zone too close to start of lane, setting start to start of lane");
                                    begin = al.LanePath().StartPoint;
                                }
                                ArbiterSafetyZone asz = new ArbiterSafetyZone(al, end, begin);
                                al.SafetyZones.Add(asz);
                                al.Way.Segment.RoadNetwork.DisplayObjects.Add(asz);
                                al.Way.Segment.RoadNetwork.ArbiterSafetyZones.Add(asz);

                                if (aw != null && aw.IsExit == true)
                                {
                                    asz.isExit = true;
                                    asz.Exit = aw;
                                }

                                // add to display
                                this.displayObjects.Add(asz);
                            }
                        }
                        else if (tool.Mode == InterToolboxMode.Helpers)
                        {
                            // create display object filter for waypoints
                            DisplayObjectFilter dof = delegate(IDisplayObject target)
                            {
                                // check if target is network object
                                if (target is ArbiterLane)
                                    return true;
                                else
                                    return false;
                            };

                            // perform hit test
                            HitTestResult htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), dof);

                            // check for validity
                            if (htr.Hit)
                            {
                                // get lane
                                ArbiterLane al = (ArbiterLane)htr.DisplayObject;

                                // get point on lane
                                tool.WrappingHelpers.Add(al.GetClosest(transform.GetWorldPoint(new PointF(e.X, e.Y))));
                            }
                        }
                        else if (tool.Mode == InterToolboxMode.Box)
                        {
                            // clicked point
                            Coordinates c = transform.GetWorldPoint(new PointF(e.X, e.Y));

                            // add points
                            if (tool.WrapInitial == null)
                            {
                                tool.WrapInitial = c;
                            }
                            else if (tool.WrapFinal != null && !tool.WrapInitial.Equals(c))
                            {
                                tool.FinalizeIntersection();
                            }
                        }
                    }
                }
                else if (this.CurrentEditorTool is ZoneTool)
                {
                    // get key current
                    KeyStateInfo shiftKey = KeyboardInfo.GetKeyState(Keys.ShiftKey);

                    ZoneTool zt = (ZoneTool)this.CurrentEditorTool;
                    if (zt.moveNode != null)
                    {
                        zt.moveNode = null;
                        zt.Reset(false);
                    }
                    else
                    {
                        if (!shiftKey.IsPressed)
                        {
                            // get key current
                            KeyStateInfo wKey = KeyboardInfo.GetKeyState(Keys.W);

                            if (!wKey.IsPressed)
                            {
                                // clicked point
                                Coordinates c = transform.GetWorldPoint(new PointF(e.X, e.Y));
                                zt.Click(c);
                            }
                            else
                            {
                                // clicked point
                                Coordinates c = transform.GetWorldPoint(new PointF(e.X, e.Y));
                                if (zt.zt.current != null && zt.zt.current.Perimeter.PerimeterPolygon.IsInside(c))
                                {
                                    zt.ed.SaveUndoPoint();
                                    zt.BeginMove(c);
                                }
                            }
                        }
                    }
                }

                this.Invalidate();
            }

            #endregion

            #region Right

            else if (e.Button == MouseButtons.Right)
            {
                if (this.CurrentEditorTool is ZoneTool)
                {
                    // clicked point
                    Coordinates c = transform.GetWorldPoint(new PointF(e.X, e.Y));

                    ZoneTool zt = (ZoneTool)this.CurrentEditorTool;
                    if (zt.zt.current != null && zt.zt.current.Perimeter.PerimeterPolygon.IsInside(c))
                    {
                        zt.RightClick(c);
                        this.Invalidate();

                        if (zt.rightClickNode != null || zt.rightClickEdge != null)
                        {
                            this.removeToolStripMenuItem.Enabled = true;
                            this.zoneContextMenuStrip.Show(this, e.X, e.Y);
                        }
                        else
                        {
                            this.removeToolStripMenuItem.Enabled = false;
                            this.zoneContextMenuStrip.Show(this, e.X, e.Y);
                        }
                    }
                }
                else if (this.CurrentEditorTool != null && this.CurrentEditorTool is PartitionTools)
                {
                    PartitionTools pt = (PartitionTools)this.CurrentEditorTool;

                    if (!pt.RemoveUserWaypointMode)
                    {
                        // create display object filter for waypoints
                        DisplayObjectFilter dof = delegate(IDisplayObject target)
                        {
                            // check if target is network object
                            if (target is ArbiterLanePartition)
                                return true;
                            else
                                return false;
                        };

                        HitTestResult htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), dof);
                        if (htr.DisplayObject != null && htr.DisplayObject is ArbiterLanePartition && htr.Hit)
                        {
                            this.selected = htr.DisplayObject;
                            this.selected.Selected = SelectionType.SingleSelected;
                            this.partitionContextMenuStrip.Show(this, e.X, e.Y);

                            pt.HitPoint = transform.GetWorldPoint(new PointF(e.X, e.Y));
                        }
                        else if (this.selected != null)
                        {
                            this.selected.Selected = SelectionType.NotSelected;
                        }
                    }
                    else
                    {
                        // create display object filter for waypoints
                        DisplayObjectFilter dof = delegate(IDisplayObject target)
                        {
                            // check if target is network object
                            if (target is ArbiterUserWaypoint)
                                return true;
                            else
                                return false;
                        };

                        HitTestResult htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), dof);
                        if (htr.DisplayObject != null && htr.DisplayObject is ArbiterUserWaypoint && htr.Hit)
                        {
                            this.selected = htr.DisplayObject;
                            this.selected.Selected = SelectionType.SingleSelected;
                            this.userWaypointContextMenuStrip.Show(this, e.X, e.Y);
                        }
                        else if (this.selected != null)
                        {
                            this.selected.Selected = SelectionType.NotSelected;
                        }
                    }

                    this.Invalidate();
                }
                else
                {
                    // perform hit test
                    HitTestResult htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), DrawingUtility.DefaultFilter);

                    if (htr.DisplayObject == null)
                    {
                    }
                    else if (htr.DisplayObject is ArbiterIntersection)
                    {
                        this.intersectionContextMenuStrip.Show(this, e.X, e.Y);
                        this.selected = htr.DisplayObject;
                    }
                    else if (this.CurrentEditorTool is IntersectionPulloutTool && ((IntersectionPulloutTool)this.CurrentEditorTool).Mode == InterToolboxMode.SafetyZone)
                    {
                        // create display object filter for waypoints
                        DisplayObjectFilter dof = delegate(IDisplayObject target)
                        {
                            // check if target is network object
                            if (target is ArbiterSafetyZone)
                                return true;
                            else
                                return false;
                        };

                        htr = this.HitTest(transform.GetWorldPoint(new PointF(e.X, e.Y)), dof);
                        if (htr.DisplayObject is ArbiterSafetyZone)
                        {
                            this.safetyZoneContextMenu.Show(this, e.X, e.Y);
                            this.selected = htr.DisplayObject;
                        }
                    }
                }
            }

            #endregion
        }
        /// <summary>
        /// Generates the xySegments into segments and inputs them into the input road network
        /// </summary>
        /// <param name="arn"></param>
        /// <returns></returns>
        public ArbiterRoadNetwork GenerateSegments(ArbiterRoadNetwork arn)
        {
            foreach (SimpleSegment ss in segments)
            {
                // seg
                ArbiterSegmentId asi = new ArbiterSegmentId(int.Parse(ss.Id));
                ArbiterSegment asg = new ArbiterSegment(asi);
                arn.ArbiterSegments.Add(asi, asg);
                asg.RoadNetwork = arn;
                asg.SpeedLimits = new ArbiterSpeedLimit();
                asg.SpeedLimits.MaximumSpeed = 13.4112; // 30mph max speed

                // way1
                ArbiterWayId awi1 = new ArbiterWayId(1, asi);
                ArbiterWay aw1 = new ArbiterWay(awi1);
                aw1.Segment = asg;
                asg.Ways.Add(awi1, aw1);
                asg.Way1 = aw1;

                // way2
                ArbiterWayId awi2 = new ArbiterWayId(2, asi);
                ArbiterWay aw2 = new ArbiterWay(awi2);
                aw2.Segment = asg;
                asg.Ways.Add(awi2, aw2);
                asg.Way2 = aw2;

                // make lanes
                foreach (SimpleLane sl in ss.Lanes)
                {
                    // lane
                    ArbiterLaneId ali;
                    ArbiterLane al;

                    // get way of lane id
                    if (ss.Way1Lanes.Contains(sl))
                    {
                        ali = new ArbiterLaneId(GenerationTools.GetId(sl.Id)[1], awi1);
                        al = new ArbiterLane(ali);
                        aw1.Lanes.Add(ali, al);
                        al.Way = aw1;
                    }
                    else
                    {
                        ali = new ArbiterLaneId(GenerationTools.GetId(sl.Id)[1], awi2);
                        al = new ArbiterLane(ali);
                        aw2.Lanes.Add(ali, al);
                        al.Way = aw2;
                    }

                    // add to display
                    arn.DisplayObjects.Add(al);

                    // width
                    al.Width = sl.LaneWidth == 0 ? TahoeParams.T * 2.0 : sl.LaneWidth * 0.3048;

                    if(sl.LaneWidth == 0)
                        Console.WriteLine("lane: " + ali.ToString() + " contains no lane width, setting to 4m");

                    // lane boundaries
                    al.BoundaryLeft = this.GenerateLaneBoundary(sl.LeftBound);
                    al.BoundaryRight = this.GenerateLaneBoundary(sl.RightBound);

                    // add lane to seg
                    asg.Lanes.Add(ali, al);

                    // waypoints
                    List<ArbiterWaypoint> waypointList = new List<ArbiterWaypoint>();

                    // generate waypoints
                    foreach (SimpleWaypoint sw in sl.Waypoints)
                    {
                        // waypoint
                        ArbiterWaypointId awi = new ArbiterWaypointId(GenerationTools.GetId(sw.ID)[2], ali);
                        ArbiterWaypoint aw = new ArbiterWaypoint(sw.Position, awi);
                        aw.Lane = al;

                        // stop
                        if (sl.Stops.Contains(sw.ID))
                        {
                            aw.IsStop = true;
                        }

                        // checkpoint
                        foreach (SimpleCheckpoint sc in sl.Checkpoints)
                        {
                            if (sw.ID == sc.WaypointId)
                            {
                                aw.IsCheckpoint = true;
                                aw.CheckpointId = int.Parse(sc.CheckpointId);
                                arn.Checkpoints.Add(aw.CheckpointId, aw);
                            }
                        }

                        // add
                        asg.Waypoints.Add(awi, aw);
                        arn.ArbiterWaypoints.Add(awi, aw);
                        al.Waypoints.Add(awi, aw);
                        waypointList.Add(aw);
                        arn.DisplayObjects.Add(aw);
                        arn.LegacyWaypointLookup.Add(sw.ID, aw);
                    }

                    al.WaypointList = waypointList;

                    // lane partitions
                    List<ArbiterLanePartition> alps = new List<ArbiterLanePartition>();
                    al.Partitions = alps;

                    // generate lane partitions
                    for (int i = 0; i < waypointList.Count-1; i++)
                    {
                        // create lane partition
                        ArbiterLanePartitionId alpi = new ArbiterLanePartitionId(waypointList[i].WaypointId, waypointList[i + 1].WaypointId, ali);
                        ArbiterLanePartition alp = new ArbiterLanePartition(alpi, waypointList[i], waypointList[i+1], asg);
                        alp.Lane = al;
                        waypointList[i].NextPartition = alp;
                        waypointList[i + 1].PreviousPartition = alp;
                        alps.Add(alp);
                        arn.DisplayObjects.Add(alp);

                        // crete initial user partition
                        ArbiterUserPartitionId aupi = new ArbiterUserPartitionId(alp.PartitionId, waypointList[i].WaypointId, waypointList[i + 1].WaypointId);
                        ArbiterUserPartition aup = new ArbiterUserPartition(aupi, alp, waypointList[i], waypointList[i + 1]);
                        List<ArbiterUserPartition> aups = new List<ArbiterUserPartition>();
                        aups.Add(aup);
                        alp.UserPartitions = aups;
                        alp.SetDefaultSparsePolygon();
                        arn.DisplayObjects.Add(aup);
                    }

                    // path segments of lane
                    List<IPathSegment> ips = new List<IPathSegment>();
                    List<Coordinates> pathSegments = new List<Coordinates>();
                    pathSegments.Add(alps[0].Initial.Position);

                    // loop
                    foreach(ArbiterLanePartition alPar in alps)
                    {
                        ips.Add(new LinePathSegment(alPar.Initial.Position, alPar.Final.Position));
                        // make new segment
                        pathSegments.Add(alPar.Final.Position);
                    }

                    // generate lane partition path
                    LinePath partitionPath = new LinePath(pathSegments);
                    al.SetLanePath(partitionPath);
                    al.PartitionPath = new Path(ips, CoordinateMode.AbsoluteProjected);

                    // safeto zones
                    foreach (ArbiterWaypoint aw in al.Waypoints.Values)
                    {
                        if(aw.IsStop)
                        {
                            LinePath.PointOnPath end = al.GetClosestPoint(aw.Position);
                            double dist = -30;
                            LinePath.PointOnPath begin = al.LanePath().AdvancePoint(end, ref dist);
                            if (dist != 0)
                            {
                                begin = al.LanePath().StartPoint;
                            }
                            ArbiterSafetyZone asz = new ArbiterSafetyZone(al, end, begin);
                            asz.isExit = true;
                            asz.Exit = aw;
                            al.SafetyZones.Add(asz);
                            arn.DisplayObjects.Add(asz);
                            arn.ArbiterSafetyZones.Add(asz);
                        }
                    }
                }
            }

            return arn;
        }
        private void ShiftNetworkOkButton_Click(object sender, EventArgs e)
        {
            try
            {
                double east = double.Parse(this.ShiftNetworkEastTextBox.Text);
                double north = double.Parse(this.ShiftNetworkNorthTextBox.Text);
                Coordinates shift = new Coordinates(east, north);

                foreach (IArbiterWaypoint iaw in roads.ArbiterWaypoints.Values)
                {
                    iaw.Position = iaw.Position + shift;
                }

                // safety zone filter
                DisplayObjectFilter f = delegate(IDisplayObject target)
                {
                    // check if target is network object
                    if (target is ArbiterSafetyZone)
                        return true;
                    else
                        return false;
                };

                // remove safety zones
                display.RemoveDisplayObjectType(f);

                // new safety
                roads.ArbiterSafetyZones = new List<ArbiterSafetyZone>();

                // remove from network
                List<IDisplayObject> displayObjects = new List<IDisplayObject>();
                foreach (IDisplayObject ido in roads.DisplayObjects)
                {
                    if (!f(ido))
                        displayObjects.Add(ido);
                }

                // remove lane safety zones, create new partition paths
                foreach (ArbiterSegment asg in roads.ArbiterSegments.Values)
                {
                    foreach (ArbiterLane al in asg.Lanes.Values)
                    {
                        al.SafetyZones = new List<ArbiterSafetyZone>();

                        // path segments of lane
                        List<IPathSegment> pathSegments = new List<IPathSegment>();

                        // loop
                        foreach (ArbiterLanePartition alPar in al.Partitions)
                        {
                            // make new segment
                            pathSegments.Add(new LinePathSegment(alPar.Initial.Position, alPar.Final.Position));
                        }

                        // generate lane partition path
                        Path partitionPath = new Path(pathSegments);
                        al.PartitionPath = partitionPath;
                    }
                }

                // recreate safety zones
                foreach (IArbiterWaypoint iaw in roads.ArbiterWaypoints.Values)
                {
                    if (iaw is ArbiterWaypoint)
                    {
                        ArbiterWaypoint aw = (ArbiterWaypoint)iaw;

                        if (aw.IsStop)
                        {
                            ArbiterLane al = aw.Lane;

                            LinePath.PointOnPath end = al.GetClosestPoint(aw.Position);
                            double dist = -30;
                            LinePath.PointOnPath begin = al.LanePath().AdvancePoint(end, ref dist);
                            if (dist != 0)
                            {
                                EditorOutput.WriteLine(aw.ToString() + " safety zone too close to start of lane, setting start to start of lane");
                                begin = al.LanePath().StartPoint;
                            }
                            ArbiterSafetyZone asz = new ArbiterSafetyZone(al, end, begin);
                            asz.isExit = true;
                            asz.Exit = aw;
                            al.SafetyZones.Add(asz);
                            roads.DisplayObjects.Add(asz);
                            roads.ArbiterSafetyZones.Add(asz);
                            display.AddDisplayObject(asz);
                        }
                    }
                }

                // redraw
                this.display.Invalidate();

                // notify
                EditorOutput.WriteLine("Shifted road network: east: " + east.ToString("F6") + ", north: " + north.ToString("F6"));
                EditorOutput.WriteLine("Recomputed position-dependent types");

                // close form
                this.Close();
            }
            catch (Exception ex)
            {
                EditorOutput.WriteLine("Shift of road network failed: \n" + ex.ToString());
            }
        }