internal void RemoveSegmentEnd(SegmentEndGeometry segmentEndGeo, GeometryCalculationMode calcMode)
        {
#if DEBUGGEO
            if (GlobalConfig.Instance.Debug.Switches[5])
            {
                Log._Debug($">>> NodeGeometry: Remove segment end {segmentEndGeo.SegmentId} @ {NodeId}, calcMode? {calcMode}");
            }
#endif

            if (calcMode == GeometryCalculationMode.Init)
            {
                return;
            }

            if (!IsValid())
            {
                //Log.Warning($"NodeGeometry: Trying to remove segment {segmentId} @ invalid node {NodeId}");
                RemoveAllSegmentEnds();
                return;
            }

            for (int i = 0; i < MAX_NUM_SEGMENTS; ++i)
            {
                if (segmentEndGeo.Equals(SegmentEndGeometries[i]))
                {
                    SegmentEndGeometries[i] = null;
                }
            }

            if (calcMode == GeometryCalculationMode.Propagate)
            {
                RecalculateSegments(segmentEndGeo.SegmentId);
            }
            Recalculate();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Registers an observer.
        /// </summary>
        /// <param name="observer"></param>
        /// <returns>An unsubscriber</returns>

        /*public IDisposable Subscribe(IObserver<NodeGeometry> observer) {
         *      try {
         *              Monitor.Enter(Lock);
         *              observers.Add(observer);
         *      } finally {
         *              Monitor.Exit(Lock);
         *      }
         *      return new GenericUnsubscriber<NodeGeometry>(observers, observer, Lock);
         * }*/

        internal void AddSegmentEnd(SegmentEndGeometry segEndGeo, GeometryCalculationMode calcMode)
        {
#if DEBUGGEO
            if (GlobalConfig.Instance.Debug.Switches[5])
            {
                Log._Debug($">>> NodeGeometry: Add segment end {segEndGeo.SegmentId}, start? {segEndGeo.StartNode} @ node {NodeId}");
            }
#endif
            if (!IsValid())
            {
                //Log.Error($"NodeGeometry: Trying to add segment {segmentId} @ invalid node {NodeId}");
                Invalidate();
                return;
            }

            bool found     = false;
            int  freeIndex = -1;
            for (int i = 0; i < MAX_NUM_SEGMENTS; ++i)
            {
                SegmentEndGeometry storedEndGeo = SegmentEndGeometries[i];
                if (segEndGeo.Equals(storedEndGeo))
                {
                    SegmentEndGeometries[i] = segEndGeo;
                    found = true;
                    break;
                }
                else if (storedEndGeo == null && freeIndex < 0)
                {
                    freeIndex = i;
                }
            }

            if (!found)
            {
                if (freeIndex >= 0)
                {
                    SegmentEndGeometries[freeIndex] = segEndGeo;
                }
                else
                {
                    Log.Error($"NodeGeometry.AddSegmentEnd: Detected inconsistency. Unable to add segment end {segEndGeo} to node {NodeId}. Maximum segment end capacity reached.");
                }
            }

            if (calcMode == GeometryCalculationMode.Propagate)
            {
                RecalculateSegments(segEndGeo.SegmentId);
            }

            if (!found && lastRemovedSegmentEndId != null)
            {
                CurrentSegmentReplacement.oldSegmentEndId = lastRemovedSegmentEndId;
                CurrentSegmentReplacement.newSegmentEndId = segEndGeo;
                lastRemovedSegmentEndId = null;
            }
            Recalculate();
        }
Ejemplo n.º 3
0
        internal void Recalculate(GeometryCalculationMode calcMode)
        {
#if DEBUGGEO
            if (GlobalConfig.Instance.Debug.Switches[5])
            {
                Log._Debug($">>> SegmentEndGeometry.Recalculate({calcMode}): seg. {SegmentId} @ node {NodeId()}");
            }
#endif

            ushort nodeIdBeforeRecalc = LastKnownNodeId;
            Cleanup();

            if (!IsValid())
            {
                if (calcMode == GeometryCalculationMode.Propagate && nodeIdBeforeRecalc != 0)
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"SegmentEndGeometry.Recalculate({calcMode}): seg. {SegmentId} is not valid. nodeIdBeforeRecalc={nodeIdBeforeRecalc}. Removing segment from node.");
                    }
#endif
                    NodeGeometry.Get(nodeIdBeforeRecalc).RemoveSegmentEnd(this, GeometryCalculationMode.Propagate);
                }

                return;
            }

            //NetManager netManager = Singleton<NetManager>.instance;

            ushort nodeId = NodeId();
            LastKnownNodeId = nodeId;

            bool oneway;
            bool outgoingOneWay;
            SegmentGeometry.calculateOneWayAtNode(SegmentId, nodeId, out oneway, out outgoingOneWay);
            OutgoingOneWay = outgoingOneWay;
            if (oneway && !OutgoingOneWay)
            {
                IncomingOneWay = true;
            }
            OnlyHighways = true;
#if DEBUGGEO
            if (GlobalConfig.Instance.Debug.Switches[5])
            {
                Log._Debug($"Checking if segment {SegmentId} is connected to highways only at node {NodeId()}. OnlyHighways={OnlyHighways}");
            }
#endif

            //ItemClass connectionClass = netManager.m_segments.m_buffer[SegmentId].Info.GetConnectionClass();

            ushort firstClockwiseSegmentId = 0;
            bool   hasOtherSegments        = false;
            for (var s = 0; s < 8; s++)
            {
                ushort otherSegmentId = 0;
                Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) {
                    otherSegmentId = node.GetSegment(s);
                    if (s == 0)
                    {
                        firstClockwiseSegmentId = otherSegmentId;
                    }
                    return(true);
                });
                if (otherSegmentId == 0 || otherSegmentId == SegmentId || !SegmentGeometry.IsValid(otherSegmentId))
                {
                    continue;
                }

                /*ItemClass otherConnectionClass = Singleton<NetManager>.instance.m_segments.m_buffer[otherSegmentId].Info.GetConnectionClass();
                 * if (otherConnectionClass.m_service != connectionClass.m_service)
                 *      continue;*/
                hasOtherSegments = true;

                // determine geometry
                bool otherIsOneWay;
                bool otherIsOutgoingOneWay;
                SegmentGeometry.calculateOneWayAtNode(otherSegmentId, nodeId, out otherIsOneWay, out otherIsOutgoingOneWay);
                bool otherIsHighway = SegmentGeometry.calculateIsHighway(otherSegmentId);

#if DEBUGGEO
                if (GlobalConfig.Instance.Debug.Switches[5])
                {
                    Log._Debug($"Segment {SegmentId} is connected to segment {otherSegmentId} at node {NodeId()}. otherIsOneWay={otherIsOneWay} otherIsOutgoingOneWay={otherIsOutgoingOneWay} otherIsHighway={otherIsHighway}");
                }
#endif
                if (!otherIsHighway || !otherIsOneWay)
                {
                    OnlyHighways = false;
                }

                if (IsRightSegment(SegmentId, otherSegmentId, nodeId))
                {
                    RightSegments[NumRightSegments++] = otherSegmentId;
                    if (!otherIsOutgoingOneWay)
                    {
                        IncomingRightSegments[NumIncomingRightSegments++] = otherSegmentId;
                        if (!otherIsOneWay)
                        {
                            OutgoingRightSegments[NumOutgoingRightSegments++] = otherSegmentId;
                        }
                    }
                    else
                    {
                        OutgoingRightSegments[NumOutgoingRightSegments++] = otherSegmentId;
                    }
                }
                else if (IsLeftSegment(SegmentId, otherSegmentId, nodeId))
                {
                    LeftSegments[NumLeftSegments++] = otherSegmentId;
                    if (!otherIsOutgoingOneWay)
                    {
                        IncomingLeftSegments[NumIncomingLeftSegments++] = otherSegmentId;
                        if (!otherIsOneWay)
                        {
                            OutgoingLeftSegments[NumOutgoingLeftSegments++] = otherSegmentId;
                        }
                    }
                    else
                    {
                        OutgoingLeftSegments[NumOutgoingLeftSegments++] = otherSegmentId;
                    }
                }
                else
                {
                    StraightSegments[NumStraightSegments++] = otherSegmentId;
                    if (!otherIsOutgoingOneWay)
                    {
                        IncomingStraightSegments[NumIncomingStraightSegments++] = otherSegmentId;
                        if (!otherIsOneWay)
                        {
                            OutgoingStraightSegments[NumOutgoingStraightSegments++] = otherSegmentId;
                        }
                    }
                    else
                    {
                        OutgoingStraightSegments[NumOutgoingStraightSegments++] = otherSegmentId;
                    }
                }

                // reset highway lane arrows
                //Flags.removeHighwayLaneArrowFlagsAtSegment(otherSegmentId); // TODO refactor

                ConnectedSegments[NumConnectedSegments++] = otherSegmentId;
            }

            NumIncomingSegments = (byte)(NumIncomingLeftSegments + NumIncomingStraightSegments + NumIncomingRightSegments);
            NumOutgoingSegments = (byte)(NumOutgoingLeftSegments + NumOutgoingStraightSegments + NumOutgoingRightSegments);

            if (!hasOtherSegments)
            {
#if DEBUGGEO
                if (GlobalConfig.Instance.Debug.Switches[5])
                {
                    Log._Debug($"Segment {SegmentId} is not connected to any other segments at node {NodeId()}.");
                }
#endif
                OnlyHighways = false;
            }

            // propagate information to other segments
            if (calcMode == GeometryCalculationMode.Init || (calcMode == GeometryCalculationMode.Propagate && nodeIdBeforeRecalc != nodeId))
            {
                if (calcMode == GeometryCalculationMode.Propagate && nodeIdBeforeRecalc != 0)
                {
                    NodeGeometry.Get(nodeIdBeforeRecalc).RemoveSegmentEnd(this, GeometryCalculationMode.Propagate);
                }

                NodeGeometry.Get(nodeId).AddSegmentEnd(this, calcMode);
            }
        }