private IEnumerable<OSMTurnInfo> EnumerateOsmTurnRestrictions(IFeatureWorkspace fws)
        {
            OSMUtility osmUtility = new OSMUtility();
            ITable tableRelation = fws.OpenTable(_osmDataset.Name + "_osm_relation");
            try
            {
                TaskManager.StartProgress(tableRelation.RowCount(null));

                using (ComReleaser cr = new ComReleaser())
                {
                    ICursor cursor = tableRelation.Search(null, false);
                    cr.ManageLifetime(cursor);

                    int idxTags = cursor.FindField("osmTags");
                    int idxMembers = cursor.FindField("osmMembers");

                    IRow row = null;
                    while ((row = cursor.NextRow()) != null)
                    {
                        tag[] tags = osmUtility.retrieveOSMTags(row, idxTags, _osmDataset.Workspace);
                        var tagsRestriction = tags.Where(t => t.k.Equals("restriction", StringComparison.CurrentCultureIgnoreCase));

                        foreach (tag tagRestrict in tagsRestriction)
                        {
                            OSMTurnInfo turn = new OSMTurnInfo();

                            turn.TurnType = tagRestrict.v;

                            foreach (member m in osmUtility.retrieveMembers(row, idxMembers))
                            {
                                if (m.role.Equals("from", StringComparison.CurrentCultureIgnoreCase))
                                    turn.From = m;
                                else if (m.role.Equals("to", StringComparison.CurrentCultureIgnoreCase))
                                    turn.To = m;
                                else if (m.role.Equals("via", StringComparison.CurrentCultureIgnoreCase))
                                    turn.Via = m;
                            }

                            if (turn.HasValidMembers())
                            {
                                turn.FromFeature = FindEdgeFeature(turn.From.@ref);
                                turn.ToFeature = FindEdgeFeature(turn.To.@ref);
                                turn.ViaFeature = FindJunctionFeature(turn.Via.@ref);

                                if (turn.HasValidFeatures())
                                    yield return turn;
                            }
                        }

                        TaskManager.StepProgress();
                    }
                }
            }
            finally
            {
                TaskManager.EndProgress();
            }
        }
        private void CreateTurnFeature_ONLY(TurnFeatureClassWrapper turnFCW, OSMTurnInfo osmTurn)
        {
            IPoint    ptVia    = osmTurn.ViaFeature.Shape as IPoint;
            IPolyline lineFrom = osmTurn.FromFeature.Shape as IPolyline;

            bool   edge1End, edge2End;
            double posFrom, posTo;
            IPoint ptStart = GetTurnEndpoint(lineFrom, ptVia, out edge1End, out posFrom);

            foreach (INetworkEdge edge in EnumerateAdjacentTurnEdges(osmTurn, edge1End))
            {
                IFeature turn = turnFCW.TurnFeatureClass.CreateFeature();

                INetworkSource srcTo     = _networkDataset.get_SourceByID(edge.SourceID);
                IFeatureClass  fcTo      = ((IFeatureClassContainer)_networkDataset).get_ClassByName(srcTo.Name);
                IFeature       featureTo = fcTo.GetFeature(edge.OID);
                IPolyline      lineTo    = featureTo.Shape as IPolyline;

                // Create Turn Shape
                IPoint ptEnd = GetTurnEndpoint(lineTo, ptVia, out edge2End, out posTo);
                turn.Shape = CreateTurnGeometry(ptStart, ptVia, ptEnd, lineFrom.SpatialReference);

                // Attributes (Edge1)
                turn.set_Value(turnFCW.idxEdge1End, (edge1End) ? "Y" : "N");
                turn.set_Value(turnFCW.idxEdge1FCID, osmTurn.FromFeature.Class.ObjectClassID);
                turn.set_Value(turnFCW.idxEdge1FID, osmTurn.FromFeature.OID);
                turn.set_Value(turnFCW.idxEdge1Pos, posFrom);

                // Attributes (Edge2)
                turn.set_Value(turnFCW.idxEdge2FCID, featureTo.Class.ObjectClassID);
                turn.set_Value(turnFCW.idxEdge2FID, featureTo.OID);
                turn.set_Value(turnFCW.idxEdge2Pos, posTo);

                // Restriction Type
                turn.set_Value(turnFCW.idxRestrict, "NO");

                turn.Store();
            }
        }
        private IEnumerable<INetworkEdge> EnumerateAdjacentTurnEdges(OSMTurnInfo osmTurn, bool useToJunction)
        {
            INetworkQuery query = (INetworkQuery)_networkDataset;

            // get turn FROM-edge
            INetworkSource source = _networkDataset.get_SourceByName(((IDataset)osmTurn.FromFeature.Class).Name);
            IEnumNetworkElement enumNetElements = query.get_EdgesByPosition(source.ID, osmTurn.FromFeature.OID, 0.0, false);
            INetworkEdge edgeFrom = enumNetElements.Next() as INetworkEdge;

            // get the FROM-edge Junctions
            INetworkJunction fromJunction = query.CreateNetworkElement(esriNetworkElementType.esriNETJunction) as INetworkJunction;
            INetworkJunction toJunction = query.CreateNetworkElement(esriNetworkElementType.esriNETJunction) as INetworkJunction;
            edgeFrom.QueryJunctions(fromJunction, toJunction);

            // Get adjacent edges from the turn center junction
            INetworkJunction junction = ((useToJunction) ? toJunction : fromJunction);
            for (int n = 0; n < junction.EdgeCount; ++n)
            {
                INetworkEdge edge = query.CreateNetworkElement(esriNetworkElementType.esriNETEdge) as INetworkEdge;
                junction.QueryEdge(n, true, edge);

                if ((edge.OID == osmTurn.FromFeature.OID) || (edge.OID == osmTurn.ToFeature.OID))
                    continue;

                yield return edge;
            }
        }
        private void CreateTurnFeature_ONLY(TurnFeatureClassWrapper turnFCW, OSMTurnInfo osmTurn)
        {
            IPoint ptVia = osmTurn.ViaFeature.Shape as IPoint;
            IPolyline lineFrom = osmTurn.FromFeature.Shape as IPolyline;

            bool edge1End, edge2End;
            double posFrom, posTo;
            IPoint ptStart = GetTurnEndpoint(lineFrom, ptVia, out edge1End, out posFrom);

            foreach (INetworkEdge edge in EnumerateAdjacentTurnEdges(osmTurn, edge1End))
            {
                IFeature turn = turnFCW.TurnFeatureClass.CreateFeature();

                INetworkSource srcTo = _networkDataset.get_SourceByID(edge.SourceID);
                IFeatureClass fcTo = ((IFeatureClassContainer)_networkDataset).get_ClassByName(srcTo.Name);
                IFeature featureTo = fcTo.GetFeature(edge.OID);
                IPolyline lineTo = featureTo.Shape as IPolyline;

                // Create Turn Shape
                IPoint ptEnd = GetTurnEndpoint(lineTo, ptVia, out edge2End, out posTo);
                turn.Shape = CreateTurnGeometry(ptStart, ptVia, ptEnd, lineFrom.SpatialReference);

                // Attributes (Edge1)
                turn.set_Value(turnFCW.idxEdge1End, (edge1End) ? "Y" : "N");
                turn.set_Value(turnFCW.idxEdge1FCID, osmTurn.FromFeature.Class.ObjectClassID);
                turn.set_Value(turnFCW.idxEdge1FID, osmTurn.FromFeature.OID);
                turn.set_Value(turnFCW.idxEdge1Pos, posFrom);

                // Attributes (Edge2)
                turn.set_Value(turnFCW.idxEdge2FCID, featureTo.Class.ObjectClassID);
                turn.set_Value(turnFCW.idxEdge2FID, featureTo.OID);
                turn.set_Value(turnFCW.idxEdge2Pos, posTo);

                // Restriction Type
                turn.set_Value(turnFCW.idxRestrict, "NO");

                turn.Store();
            }
        }
        private void CreateTurnFeature_NO(TurnFeatureClassWrapper turnFCW, OSMTurnInfo osmTurn)
        {
            IFeature turn = turnFCW.TurnFeatureClass.CreateFeature();

            IPoint ptVia = osmTurn.ViaFeature.Shape as IPoint;
            IPolyline lineFrom = osmTurn.FromFeature.Shape as IPolyline;
            IPolyline lineTo = osmTurn.ToFeature.Shape as IPolyline;

            // Create Turn Shape
            bool edge1End, edge2End;
            double posFrom, posTo;
            IPoint ptStart = GetTurnEndpoint(lineFrom, ptVia, out edge1End, out posFrom);
            IPoint ptEnd = GetTurnEndpoint(lineTo, ptVia, out edge2End, out posTo);
            turn.Shape = CreateTurnGeometry(ptStart, ptVia, ptEnd, lineFrom.SpatialReference);

            // Attributes (Edge1)
            turn.set_Value(turnFCW.idxEdge1End, (edge1End) ? "Y" : "N");
            turn.set_Value(turnFCW.idxEdge1FCID, osmTurn.FromFeature.Class.ObjectClassID);
            turn.set_Value(turnFCW.idxEdge1FID, osmTurn.FromFeature.OID);
            turn.set_Value(turnFCW.idxEdge1Pos, posFrom);

            // Attributes (Edge2)
            turn.set_Value(turnFCW.idxEdge2FCID, osmTurn.ToFeature.Class.ObjectClassID);
            turn.set_Value(turnFCW.idxEdge2FID, osmTurn.ToFeature.OID);
            turn.set_Value(turnFCW.idxEdge2Pos, posTo);

            // Restriction Type
            turn.set_Value(turnFCW.idxRestrict, osmTurn.TurnType);

            turn.Store();
        }
        private IEnumerable <OSMTurnInfo> EnumerateOsmTurnRestrictions(IFeatureWorkspace fws)
        {
            OSMUtility osmUtility    = new OSMUtility();
            ITable     tableRelation = fws.OpenTable(_osmDataset.Name + "_osm_relation");

            try
            {
                TaskManager.StartProgress(tableRelation.RowCount(null));

                using (ComReleaser cr = new ComReleaser())
                {
                    ICursor cursor = tableRelation.Search(null, false);
                    cr.ManageLifetime(cursor);

                    int idxTags    = cursor.FindField("osmTags");
                    int idxMembers = cursor.FindField("osmMembers");

                    IRow row = null;
                    while ((row = cursor.NextRow()) != null)
                    {
                        tag[] tags            = osmUtility.retrieveOSMTags(row, idxTags, _osmDataset.Workspace);
                        var   tagsRestriction = tags.Where(t => t.k.Equals("restriction", StringComparison.CurrentCultureIgnoreCase));

                        foreach (tag tagRestrict in tagsRestriction)
                        {
                            OSMTurnInfo turn = new OSMTurnInfo();

                            turn.TurnType = tagRestrict.v;

                            foreach (member m in osmUtility.retrieveMembers(row, idxMembers))
                            {
                                if (m.role.Equals("from", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    turn.From = m;
                                }
                                else if (m.role.Equals("to", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    turn.To = m;
                                }
                                else if (m.role.Equals("via", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    turn.Via = m;
                                }
                            }

                            if (turn.HasValidMembers())
                            {
                                turn.FromFeature = FindEdgeFeature(turn.From.@ref);
                                turn.ToFeature   = FindEdgeFeature(turn.To.@ref);
                                turn.ViaFeature  = FindJunctionFeature(turn.Via.@ref);

                                if (turn.HasValidFeatures())
                                {
                                    yield return(turn);
                                }
                            }
                        }

                        TaskManager.StepProgress();
                    }
                }
            }
            finally
            {
                TaskManager.EndProgress();
            }
        }
        private IEnumerable<INetworkEdge> EnumerateAdjacentTurnEdges(OSMTurnInfo osmTurn, bool useToJunction)
        {
            INetworkQuery query = (INetworkQuery)_networkDataset;

            // get turn FROM-edge
            INetworkSource source = _networkDataset.get_SourceByName(((IDataset)osmTurn.FromFeature.Class).Name);
            IEnumNetworkElement enumNetElements = null;

            IRelationalOperator relationalOperator = ((IPolyline)osmTurn.ToFeature.Shape).FromPoint as IRelationalOperator;

            bool useFromPointOfToFeature = relationalOperator.Contains(osmTurn.ViaFeature.Shape);

            if (useFromPointOfToFeature)
                enumNetElements = query.get_EdgesByPosition(source.ID, osmTurn.ToFeature.OID, 0, false);
            else
                enumNetElements = query.get_EdgesByPosition(source.ID, osmTurn.ToFeature.OID, 1, false);

            INetworkEdge edgeFrom = enumNetElements.Next() as INetworkEdge;

            // get the FROM-edge Junctions
            INetworkJunction fromJunction = query.CreateNetworkElement(esriNetworkElementType.esriNETJunction) as INetworkJunction;
            INetworkJunction toJunction = query.CreateNetworkElement(esriNetworkElementType.esriNETJunction) as INetworkJunction;

            edgeFrom.QueryJunctions(fromJunction, toJunction);

            // Get adjacent edges from the turn center junction
            INetworkJunction junction = ((useFromPointOfToFeature) ? fromJunction : toJunction);

            for (int n = 0; n < junction.EdgeCount; ++n)
            {
                INetworkEdge edge = query.CreateNetworkElement(esriNetworkElementType.esriNETEdge) as INetworkEdge;
                if (useFromPointOfToFeature)
                    junction.QueryEdge(n, true, edge);
                else
                    junction.QueryEdge(n, false, edge);

                //if ((edge.SourceID == osmTurn.FromFeature.OID) || (edge.SourceID == osmTurn.ToFeature.OID))
                if ((edge.OID == osmTurn.ToFeature.OID))
                    continue;

                yield return edge;
            }
        }