/// <summary>
        /// finish the wrapping and cretae the intersection
        /// </summary>
        public void FinalizeIntersection()
        {
            // finalize the intersection polygon
            Polygon sq = this.CreateSquarePolygon(this.WrapInitial.Value, this.WrapFinal.Value).Inflate(1.0);
            Polygon interPoly = this.CreateIntersectionPolygon(sq);

            // check poly not null
            if (interPoly != null)
            {
                // inflate the inter poly
                interPoly = interPoly.Inflate(0.05);

                // retreive all exits involved in this intersection
                Dictionary<IAreaSubtypeWaypointId, ITraversableWaypoint> exits = this.IntersectionExits(sq);

                // make sure the inter contains an exit
                if (exits.Count > 0)
                {
                    // make stopped exits, necessarily these are arbiter waypoints not perimeter points
                    List<ArbiterStoppedExit> ases = this.CreateStoppedExits(exits.Values);

                    // construct intersection id
                    ITraversableWaypoint[] exitArray = new ITraversableWaypoint[exits.Count];
                    exits.Values.CopyTo(exitArray, 0);
                    ArbiterIntersectionId aii = new ArbiterIntersectionId(exitArray[0].Exits[0].InterconnectId);

                    // determine incoming lanes
                    Dictionary<ArbiterLane, LinePath.PointOnPath> incoming = this.DetermineIncoming(interPoly);

                    // create the intersection
                    ArbiterIntersection ai = new ArbiterIntersection(
                        interPoly,
                        ases,
                        this.DetermineInvolved(exits.Values, incoming),
                        incoming,
                        exits,
                        interPoly.Center,
                        aii,
                        arn,
                        this.IntersectionEntries(sq)
                        );

                    // create safety zones
                    this.CreateSafetyImplicitZones(ai);

                    // update poly
                    //this.UpdateIntersectionPolygon(ai);

                    /*List<Polygon> ps = new List<Polygon>();
                    foreach (ITraversableWaypoint itw in exits.Values)
                    {
                        foreach (ArbiterInterconnect ait in itw.Exits)
                        {
                            ps.Add(ait.TurnPolygon);
                        }
                    }
                    ai.IntersectionPolygon = this.GetIntersectionPolygon(ps, ai.AllExits, ai.AllEntries);*/
                    //ai.IntersectionPolygon = UrbanChallenge.Arbiter.Core.Common.Tools.PolygonToolkit.PolygonUnion(ps);
                    try
                    {
                        List<Polygon> ps = new List<Polygon>();
                        foreach (ITraversableWaypoint itw in exits.Values)
                        {
                            foreach (ArbiterInterconnect ait in itw.Exits)
                            {
                                ps.Add(ait.TurnPolygon);
                            }
                        }
                        ai.IntersectionPolygon = this.GetIntersectionPolygon(ps, ai.AllExits, ai.AllEntries);

                        if (ai.IntersectionPolygon.IsComplex)
                        {
                            EditorOutput.WriteLine("Intersection polygon complex, defaulting");
                            throw new Exception("complex polygon exception");
                        }
                    }
                    catch (Exception)
                    {
                        EditorOutput.WriteLine("Error in union polygon generation, using better default");

                        try
                        {
                            this.UpdateIntersectionPolygon(ai);
                        }
                        catch (Exception)
                        {
                            EditorOutput.WriteLine("Error in my simple polygon generation, plain default");
                            List<Coordinates> cs = new List<Coordinates>();
                            foreach (ITraversableWaypoint itw in ai.AllEntries.Values)
                                cs.Add(itw.Position);
                            foreach (ITraversableWaypoint itw in ai.AllExits.Values)
                            {
                                cs.Add(itw.Position);
                                foreach (ArbiterInterconnect aint in itw.Exits)
                                {
                                    cs.AddRange(aint.TurnPolygon);
                                }
                            }
                            ai.IntersectionPolygon = Polygon.GrahamScan(cs);
                        }
                    }

                    try
                    {
                        // add intersection
                        arn.ArbiterIntersections.Add(aii, ai);

                        // add to exit lookup
                        foreach (IAreaSubtypeWaypointId awi in exits.Keys)
                        {
                            if (arn.IntersectionLookup.ContainsKey(awi))
                                arn.IntersectionLookup[awi] = ai;
                            else
                                arn.IntersectionLookup.Add(awi, ai);
                        }

                        // add to display objects
                        arn.DisplayObjects.Add(ai);
                        rd.AddDisplayObject(ai);
                    }
                    catch (Exception e)
                    {
                        EditorOutput.WriteLine("Error adding intersection: " + aii.ToString());
                        EditorOutput.WriteLine("Error adding intersection: " + e.ToString());
                    }
                }
            }

            // reset the tool
            this.it.ResetIcons();
            this.WrapFinal = null;
            this.WrapInitial = null;
        }