Exemple #1
0
        public void VerifyValid()
        {
            Fixture.CustomizePolylineM();

            var data = new Messages.AddRoadSegment
            {
                TemporaryId          = Fixture.Create <RoadSegmentId>(),
                StartNodeId          = Fixture.Create <RoadNodeId>(),
                EndNodeId            = Fixture.Create <RoadNodeId>(),
                Geometry             = GeometryTranslator.Translate(Fixture.Create <MultiLineString>()),
                MaintenanceAuthority = Fixture.Create <OrganizationId>(),
                GeometryDrawMethod   = Fixture.Create <RoadSegmentGeometryDrawMethod>(),
                Morphology           = Fixture.Create <RoadSegmentMorphology>(),
                Status                = Fixture.Create <RoadSegmentStatus>(),
                Category              = Fixture.Create <RoadSegmentCategory>(),
                AccessRestriction     = Fixture.Create <RoadSegmentAccessRestriction>(),
                LeftSideStreetNameId  = Fixture.Create <int?>(),
                RightSideStreetNameId = Fixture.Create <int?>(),
                Lanes    = Fixture.CreateMany <RequestedRoadSegmentLaneAttribute>().ToArray(),
                Widths   = Fixture.CreateMany <RequestedRoadSegmentWidthAttribute>().ToArray(),
                Surfaces = Fixture.CreateMany <RequestedRoadSegmentSurfaceAttribute>().ToArray(),
            };

            Validator.ValidateAndThrow(data);
        }
Exemple #2
0
        public void VerifyValid()
        {
            var data = GeometryTranslator.Translate(Fixture.Create <MultiLineString>());

            data.SpatialReferenceSystemIdentifier = SpatialReferenceSystemIdentifier.BelgeLambert1972.ToInt32();

            Validator.ValidateAndThrow(data);
        }
        public void VerifyValid()
        {
            Fixture.CustomizePolylineM();

            var geometry = GeometryTranslator.Translate(Fixture.Create <MultiLineString>());
            var data     = geometry.MultiLineString[new Random().Next(0, geometry.MultiLineString.Length)];

            Validator.ValidateAndThrow(data);
        }
Exemple #4
0
        private RoadNetworkView Given(Messages.RoadSegmentAdded @event)
        {
            var id    = new RoadSegmentId(@event.Id);
            var start = new RoadNodeId(@event.StartNodeId);
            var end   = new RoadNodeId(@event.EndNodeId);

            var attributeHash = AttributeHash.None
                                .With(RoadSegmentAccessRestriction.Parse(@event.AccessRestriction))
                                .With(RoadSegmentCategory.Parse(@event.Category))
                                .With(RoadSegmentMorphology.Parse(@event.Morphology))
                                .With(RoadSegmentStatus.Parse(@event.Status))
                                .WithLeftSide(@event.LeftSide.StreetNameId.HasValue
                    ? new CrabStreetnameId(@event.LeftSide.StreetNameId.Value)
                    : new CrabStreetnameId?())
                                .WithRightSide(@event.RightSide.StreetNameId.HasValue
                    ? new CrabStreetnameId(@event.RightSide.StreetNameId.Value)
                    : new CrabStreetnameId?())
                                .With(new OrganizationId(@event.MaintenanceAuthority.Code));

            var segment = new RoadSegment(
                id,
                GeometryTranslator.Translate(@event.Geometry),
                start,
                end,
                attributeHash);

            return(new RoadNetworkView(
                       _nodes
                       .TryReplace(start, node => node.ConnectWith(id))
                       .TryReplace(end, node => node.ConnectWith(id)),
                       _segments.Add(id, segment),
                       _maximumNodeId,
                       RoadSegmentId.Max(id, _maximumSegmentId),
                       _maximumGradeSeparatedJunctionId,
                       _maximumEuropeanRoadAttributeId,
                       _maximumNationalRoadAttributeId,
                       _maximumNumberedRoadAttributeId,
                       @event.Lanes.Length != 0
                    ? AttributeId.Max(
                           new AttributeId(@event.Lanes.Max(_ => _.AttributeId)),
                           _maximumLaneAttributeId)
                    : _maximumLaneAttributeId,
                       @event.Widths.Length != 0
                    ? AttributeId.Max(
                           new AttributeId(@event.Widths.Max(_ => _.AttributeId)),
                           _maximumWidthAttributeId)
                    : _maximumWidthAttributeId,
                       @event.Surfaces.Length != 0
                    ? AttributeId.Max(
                           new AttributeId(@event.Surfaces.Max(_ => _.AttributeId)),
                           _maximumSurfaceAttributeId)
                    : _maximumSurfaceAttributeId,
                       _segmentReusableLaneAttributeIdentifiers.AddOrMergeDistinct(id, @event.Lanes.Select(lane => new AttributeId(lane.AttributeId))),
                       _segmentReusableWidthAttributeIdentifiers.AddOrMergeDistinct(id, @event.Widths.Select(width => new AttributeId(width.AttributeId))),
                       _segmentReusableSurfaceAttributeIdentifiers.AddOrMergeDistinct(id, @event.Surfaces.Select(surface => new AttributeId(surface.AttributeId)))
                       ));
        }
Exemple #5
0
        public void VerifyValid()
        {
            Fixture.CustomizePoint();

            var data = GeometryTranslator.Translate(Fixture.Create <NetTopologySuite.Geometries.Point>());

            data.SpatialReferenceSystemIdentifier = SpatialReferenceSystemIdentifier.BelgeLambert1972.ToInt32();

            Validator.ValidateAndThrow(data);
        }
Exemple #6
0
        private AddRoadNode Translate(Messages.AddRoadNode command)
        {
            var permanent = _nextRoadNodeId();
            var temporary = new RoadNodeId(command.TemporaryId);

            return(new AddRoadNode
                   (
                       permanent,
                       temporary,
                       RoadNodeType.Parse(command.Type),
                       GeometryTranslator.Translate(command.Geometry)
                   ));
        }
        public void TranslateTo(Messages.RejectedChange message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            message.AddRoadSegment = new Messages.AddRoadSegment
            {
                TemporaryId          = TemporaryId,
                StartNodeId          = TemporaryStartNodeId ?? StartNodeId,
                EndNodeId            = TemporaryEndNodeId ?? EndNodeId,
                Geometry             = GeometryTranslator.Translate(Geometry),
                MaintenanceAuthority = MaintenanceAuthority,
                GeometryDrawMethod   = GeometryDrawMethod,
                Morphology           = Morphology,
                Status                = Status,
                Category              = Category,
                AccessRestriction     = AccessRestriction,
                LeftSideStreetNameId  = LeftSideStreetNameId.GetValueOrDefault(),
                RightSideStreetNameId = RightSideStreetNameId.GetValueOrDefault(),
                Lanes = Lanes
                        .Select(item => new Messages.RequestedRoadSegmentLaneAttribute
                {
                    AttributeId  = item.TemporaryId,
                    Count        = item.Count,
                    Direction    = item.Direction,
                    FromPosition = item.From,
                    ToPosition   = item.To
                })
                        .ToArray(),
                Widths = Widths
                         .Select(item => new Messages.RequestedRoadSegmentWidthAttribute
                {
                    AttributeId  = item.TemporaryId,
                    Width        = item.Width,
                    FromPosition = item.From,
                    ToPosition   = item.To
                })
                         .ToArray(),
                Surfaces = Surfaces
                           .Select(item => new Messages.RequestedRoadSegmentSurfaceAttribute
                {
                    AttributeId  = item.TemporaryId,
                    Type         = item.Type,
                    FromPosition = item.From,
                    ToPosition   = item.To
                })
                           .ToArray()
            };
        }
        public void TranslateTo(Messages.RejectedChange message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            message.AddRoadNode = new Messages.AddRoadNode
            {
                TemporaryId = TemporaryId,
                Type        = Type.ToString(),
                Geometry    = GeometryTranslator.Translate(Geometry)
            };
        }
Exemple #9
0
 public Messages.RoadNetworkSnapshot TakeSnapshot()
 {
     return(new Messages.RoadNetworkSnapshot
     {
         Nodes = _nodes.Select(node => new Messages.RoadNetworkSnapshotNode
         {
             Id = node.Value.Id.ToInt32(),
             Segments = node.Value.Segments.Select(segment => segment.ToInt32()).ToArray(),
             Geometry = GeometryTranslator.Translate(node.Value.Geometry)
         }).ToArray(),
         Segments = _segments.Select(segment => new Messages.RoadNetworkSnapshotSegment
         {
             Id = segment.Value.Id.ToInt32(),
             StartNodeId = segment.Value.Start.ToInt32(),
             EndNodeId = segment.Value.End.ToInt32(),
             Geometry = GeometryTranslator.Translate(segment.Value.Geometry),
             AttributeHash = segment.Value.AttributeHash.GetHashCode()
         }).ToArray(),
         MaximumNodeId = _maximumNodeId.ToInt32(),
         MaximumSegmentId = _maximumSegmentId.ToInt32(),
         MaximumGradeSeparatedJunctionId = _maximumGradeSeparatedJunctionId.ToInt32(),
         MaximumEuropeanRoadAttributeId = _maximumEuropeanRoadAttributeId.ToInt32(),
         MaximumNationalRoadAttributeId = _maximumNationalRoadAttributeId.ToInt32(),
         MaximumNumberedRoadAttributeId = _maximumNumberedRoadAttributeId.ToInt32(),
         MaximumLaneAttributeId = _maximumLaneAttributeId.ToInt32(),
         MaximumWidthAttributeId = _maximumWidthAttributeId.ToInt32(),
         MaximumSurfaceAttributeId = _maximumSurfaceAttributeId.ToInt32(),
         SegmentReusableLaneAttributeIdentifiers = _segmentReusableLaneAttributeIdentifiers.Select(segment =>
                                                                                                   new Messages.RoadNetworkSnapshotSegmentReusableAttributeIdentifiers
         {
             SegmentId = segment.Key.ToInt32(),
             ReusableAttributeIdentifiers = segment.Value.Select(lane => lane.ToInt32()).ToArray()
         }).ToArray(),
         SegmentReusableWidthAttributeIdentifiers = _segmentReusableWidthAttributeIdentifiers.Select(segment =>
                                                                                                     new Messages.RoadNetworkSnapshotSegmentReusableAttributeIdentifiers
         {
             SegmentId = segment.Key.ToInt32(),
             ReusableAttributeIdentifiers = segment.Value.Select(width => width.ToInt32()).ToArray()
         }).ToArray(),
         SegmentReusableSurfaceAttributeIdentifiers = _segmentReusableSurfaceAttributeIdentifiers.Select(segment =>
                                                                                                         new Messages.RoadNetworkSnapshotSegmentReusableAttributeIdentifiers
         {
             SegmentId = segment.Key.ToInt32(),
             ReusableAttributeIdentifiers = segment.Value.Select(surface => surface.ToInt32()).ToArray()
         }).ToArray()
     });
 }
Exemple #10
0
        private RoadNetworkView Given(Messages.RoadNodeAdded @event)
        {
            var id   = new RoadNodeId(@event.Id);
            var node = new RoadNode(id, GeometryTranslator.Translate(@event.Geometry));

            return(new RoadNetworkView(
                       _nodes.Add(id, node),
                       _segments,
                       RoadNodeId.Max(id, _maximumNodeId),
                       _maximumSegmentId,
                       _maximumGradeSeparatedJunctionId,
                       _maximumEuropeanRoadAttributeId,
                       _maximumNationalRoadAttributeId,
                       _maximumNumberedRoadAttributeId,
                       _maximumLaneAttributeId,
                       _maximumWidthAttributeId,
                       _maximumSurfaceAttributeId,
                       _segmentReusableLaneAttributeIdentifiers,
                       _segmentReusableWidthAttributeIdentifiers,
                       _segmentReusableSurfaceAttributeIdentifiers));
        }
Exemple #11
0
        public RoadNetworkView Given(Messages.ImportedRoadNode @event)
        {
            if (@event == null)
            {
                throw new ArgumentNullException(nameof(@event));
            }
            var id   = new RoadNodeId(@event.Id);
            var node = new RoadNode(id, GeometryTranslator.Translate(@event.Geometry));

            return(new RoadNetworkView(
                       _nodes.Add(id, node),
                       _segments,
                       RoadNodeId.Max(id, _maximumNodeId),
                       _maximumSegmentId, _maximumGradeSeparatedJunctionId,
                       _maximumEuropeanRoadAttributeId,
                       _maximumNationalRoadAttributeId,
                       _maximumNumberedRoadAttributeId,
                       _maximumLaneAttributeId,
                       _maximumWidthAttributeId,
                       _maximumSurfaceAttributeId,
                       _segmentReusableLaneAttributeIdentifiers,
                       _segmentReusableWidthAttributeIdentifiers,
                       _segmentReusableSurfaceAttributeIdentifiers));
        }
        public ChangeRoadNetworkValidatorTests()
        {
            Fixture = new Fixture();
            Fixture.CustomizePoint();
            Fixture.CustomizePolylineM();

            Fixture.CustomizeRoadNodeId();
            Fixture.CustomizeRoadNodeType();
            Fixture.CustomizeRoadSegmentId();
            Fixture.CustomizeRoadSegmentCategory();
            Fixture.CustomizeRoadSegmentMorphology();
            Fixture.CustomizeRoadSegmentStatus();
            Fixture.CustomizeRoadSegmentAccessRestriction();
            Fixture.CustomizeRoadSegmentLaneCount();
            Fixture.CustomizeRoadSegmentLaneDirection();
            Fixture.CustomizeRoadSegmentNumberedRoadDirection();
            Fixture.CustomizeRoadSegmentGeometryDrawMethod();
            Fixture.CustomizeRoadSegmentNumberedRoadOrdinal();
            Fixture.CustomizeRoadSegmentSurfaceType();
            Fixture.CustomizeRoadSegmentWidth();
            Fixture.CustomizeEuropeanRoadNumber();
            Fixture.CustomizeNationalRoadNumber();
            Fixture.CustomizeNumberedRoadNumber();
            Fixture.CustomizeGradeSeparatedJunctionId();
            Fixture.CustomizeGradeSeparatedJunctionType();

            Fixture.Customize <RoadSegmentEuropeanRoadAttributes>(composer =>
                                                                  composer.Do(instance =>
            {
                instance.AttributeId = Fixture.Create <AttributeId>();
                instance.Number      = Fixture.Create <EuropeanRoadNumber>();
            }).OmitAutoProperties());
            Fixture.Customize <RoadSegmentNationalRoadAttributes>(composer =>
                                                                  composer.Do(instance =>
            {
                instance.AttributeId = Fixture.Create <AttributeId>();
                instance.Ident2      = Fixture.Create <NationalRoadNumber>();
            }).OmitAutoProperties());
            Fixture.Customize <RoadSegmentNumberedRoadAttributes>(composer =>
                                                                  composer.Do(instance =>
            {
                instance.AttributeId = Fixture.Create <AttributeId>();
                instance.Ident8      = Fixture.Create <NumberedRoadNumber>();
                instance.Direction   = Fixture.Create <RoadSegmentNumberedRoadDirection>();
                instance.Ordinal     = Fixture.Create <RoadSegmentNumberedRoadOrdinal>();
            }).OmitAutoProperties());
            Fixture.Customize <Messages.RoadSegmentLaneAttributes>(composer =>
                                                                   composer.Do(instance =>
            {
                var positionGenerator = new Generator <RoadSegmentPosition>(Fixture);
                instance.AttributeId  = Fixture.Create <AttributeId>();
                instance.FromPosition = positionGenerator.First(candidate => candidate >= 0.0m);
                instance.ToPosition   = positionGenerator.First(candidate => candidate > instance.FromPosition);
                instance.Count        = Fixture.Create <RoadSegmentLaneCount>();
                instance.Direction    = Fixture.Create <RoadSegmentLaneDirection>();
            }).OmitAutoProperties());
            Fixture.Customize <Messages.RoadSegmentWidthAttributes>(composer =>
                                                                    composer.Do(instance =>
            {
                var positionGenerator = new Generator <RoadSegmentPosition>(Fixture);
                instance.AttributeId  = Fixture.Create <AttributeId>();
                instance.FromPosition = positionGenerator.First(candidate => candidate >= 0.0m);
                instance.ToPosition   = positionGenerator.First(candidate => candidate > instance.FromPosition);
                instance.Width        = Fixture.Create <RoadSegmentWidth>();
            }).OmitAutoProperties());
            Fixture.Customize <Messages.RoadSegmentSurfaceAttributes>(composer =>
                                                                      composer.Do(instance =>
            {
                var positionGenerator = new Generator <RoadSegmentPosition>(Fixture);
                instance.AttributeId  = Fixture.Create <AttributeId>();
                instance.FromPosition = positionGenerator.First(candidate => candidate >= 0.0m);
                instance.ToPosition   = positionGenerator.First(candidate => candidate > instance.FromPosition);
                instance.Type         = Fixture.Create <RoadSegmentSurfaceType>();
            }).OmitAutoProperties());

            Fixture.Customize <Messages.AddRoadNode>(
                composer =>
                composer.FromFactory(random =>
                                     new Messages.AddRoadNode
            {
                TemporaryId = Fixture.Create <RoadNodeId>(),
                Type        = Fixture.Create <RoadNodeType>(),
                Geometry    = Fixture.Create <RoadNodeGeometry>()
            }
                                     )
                );
            Fixture.Customize <Messages.AddRoadSegment>(
                composer =>
                composer.FromFactory(random =>
                                     new Messages.AddRoadSegment
            {
                TemporaryId          = Fixture.Create <RoadSegmentId>(),
                StartNodeId          = Fixture.Create <RoadNodeId>(),
                EndNodeId            = Fixture.Create <RoadNodeId>(),
                Geometry             = GeometryTranslator.Translate(Fixture.Create <MultiLineString>()),
                MaintenanceAuthority = Fixture.Create <string>(),
                GeometryDrawMethod   = Fixture.Create <RoadSegmentGeometryDrawMethod>(),
                Morphology           = Fixture.Create <RoadSegmentMorphology>(),
                Status                = Fixture.Create <RoadSegmentStatus>(),
                Category              = Fixture.Create <RoadSegmentCategory>(),
                AccessRestriction     = Fixture.Create <RoadSegmentAccessRestriction>(),
                LeftSideStreetNameId  = Fixture.Create <Nullable <int> >(),
                RightSideStreetNameId = Fixture.Create <Nullable <int> >(),
                Lanes    = Fixture.CreateMany <RequestedRoadSegmentLaneAttribute>().ToArray(),
                Widths   = Fixture.CreateMany <RequestedRoadSegmentWidthAttribute>().ToArray(),
                Surfaces = Fixture.CreateMany <RequestedRoadSegmentSurfaceAttribute>().ToArray()
            }).OmitAutoProperties()
                );
            Fixture.Customize <Messages.AddGradeSeparatedJunction>(
                composer =>
                composer.FromFactory(random =>
                                     new Messages.AddGradeSeparatedJunction
            {
                TemporaryId    = Fixture.Create <GradeSeparatedJunctionId>(),
                UpperSegmentId = Fixture.Create <RoadSegmentId>(),
                LowerSegmentId = Fixture.Create <RoadSegmentId>(),
                Type           = Fixture.Create <GradeSeparatedJunctionType>()
            }
                                     ).OmitAutoProperties()
                );
            Fixture.Customize <RequestedChange>(
                composer =>
                composer.FromFactory(random =>
            {
                var result = new RequestedChange();
                switch (random.Next(0, 3))
                {
                case 0:
                    result.AddRoadNode = Fixture.Create <Messages.AddRoadNode>();
                    break;

                case 1:
                    result.AddRoadSegment = Fixture.Create <Messages.AddRoadSegment>();
                    break;

                case 2:
                    result.AddGradeSeparatedJunction = Fixture.Create <Messages.AddGradeSeparatedJunction>();
                    break;
                }
                return(result);
            }
                                     ).OmitAutoProperties()
                );
            Validator = new ChangeRoadNetworkValidator();
        }
Exemple #13
0
        private AddRoadSegment Translate(Messages.AddRoadSegment command, IRequestedChangeIdentityTranslator translator)
        {
            var permanent = _nextRoadSegmentId();
            var temporary = new RoadSegmentId(command.TemporaryId);

            var        startNodeId = new RoadNodeId(command.StartNodeId);
            RoadNodeId?temporaryStartNodeId;

            if (translator.TryTranslateToPermanent(startNodeId, out var permanentStartNodeId))
            {
                temporaryStartNodeId = startNodeId;
                startNodeId          = permanentStartNodeId;
            }
            else
            {
                temporaryStartNodeId = null;
            }

            var        endNodeId = new RoadNodeId(command.EndNodeId);
            RoadNodeId?temporaryEndNodeId;

            if (translator.TryTranslateToPermanent(endNodeId, out var permanentEndNodeId))
            {
                temporaryEndNodeId = endNodeId;
                endNodeId          = permanentEndNodeId;
            }
            else
            {
                temporaryEndNodeId = null;
            }

            var geometry             = GeometryTranslator.Translate(command.Geometry);
            var maintainer           = new OrganizationId(command.MaintenanceAuthority);
            var geometryDrawMethod   = RoadSegmentGeometryDrawMethod.Parse(command.GeometryDrawMethod);
            var morphology           = RoadSegmentMorphology.Parse(command.Morphology);
            var status               = RoadSegmentStatus.Parse(command.Status);
            var category             = RoadSegmentCategory.Parse(command.Category);
            var accessRestriction    = RoadSegmentAccessRestriction.Parse(command.AccessRestriction);
            var leftSideStreetNameId = command.LeftSideStreetNameId.HasValue
                ? new CrabStreetnameId(command.LeftSideStreetNameId.Value)
                : new CrabStreetnameId?();
            var rightSideStreetNameId = command.RightSideStreetNameId.HasValue
                ? new CrabStreetnameId(command.RightSideStreetNameId.Value)
                : new CrabStreetnameId?();
            var nextLaneAttributeId = _nextRoadSegmentLaneAttributeId(permanent);
            var laneAttributes      = Array.ConvertAll(
                command.Lanes,
                item => new RoadSegmentLaneAttribute(
                    nextLaneAttributeId(),
                    new AttributeId(item.AttributeId),
                    new RoadSegmentLaneCount(item.Count),
                    RoadSegmentLaneDirection.Parse(item.Direction),
                    new RoadSegmentPosition(item.FromPosition),
                    new RoadSegmentPosition(item.ToPosition),
                    new GeometryVersion(0)
                    )
                );
            var nextWidthAttributeId = _nextRoadSegmentWidthAttributeId(permanent);
            var widthAttributes      = Array.ConvertAll(
                command.Widths,
                item => new RoadSegmentWidthAttribute(
                    nextWidthAttributeId(),
                    new AttributeId(item.AttributeId),
                    new RoadSegmentWidth(item.Width),
                    new RoadSegmentPosition(item.FromPosition),
                    new RoadSegmentPosition(item.ToPosition),
                    new GeometryVersion(0)
                    )
                );
            var nextSurfaceAttributeId = _nextRoadSegmentSurfaceAttributeId(permanent);
            var surfaceAttributes      = Array.ConvertAll(
                command.Surfaces,
                item => new RoadSegmentSurfaceAttribute(
                    nextSurfaceAttributeId(),
                    new AttributeId(item.AttributeId),
                    RoadSegmentSurfaceType.Parse(item.Type),
                    new RoadSegmentPosition(item.FromPosition),
                    new RoadSegmentPosition(item.ToPosition),
                    new GeometryVersion(0)
                    )
                );

            return(new AddRoadSegment
                   (
                       permanent,
                       temporary,
                       startNodeId,
                       temporaryStartNodeId,
                       endNodeId,
                       temporaryEndNodeId,
                       geometry,
                       maintainer,
                       geometryDrawMethod,
                       morphology,
                       status,
                       category,
                       accessRestriction,
                       leftSideStreetNameId,
                       rightSideStreetNameId,
                       laneAttributes,
                       widthAttributes,
                       surfaceAttributes
                   ));
        }
Exemple #14
0
        public RoadNetworkView RestoreFromSnapshot(Messages.RoadNetworkSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            return(new RoadNetworkView(
                       snapshot.Nodes.ToImmutableDictionary(node => new RoadNodeId(node.Id),
                                                            node => new RoadNode(new RoadNodeId(node.Id), GeometryTranslator.Translate(node.Geometry))),
                       snapshot.Segments.ToImmutableDictionary(segment => new RoadSegmentId(segment.Id),
                                                               segment => new RoadSegment(new RoadSegmentId(segment.Id),
                                                                                          GeometryTranslator.Translate(segment.Geometry), new RoadNodeId(segment.StartNodeId),
                                                                                          new RoadNodeId(segment.EndNodeId), AttributeHash.FromHashCode(segment.AttributeHash))),
                       new RoadNodeId(snapshot.MaximumNodeId),
                       new RoadSegmentId(snapshot.MaximumSegmentId),
                       new GradeSeparatedJunctionId(snapshot.MaximumGradeSeparatedJunctionId),
                       new AttributeId(snapshot.MaximumEuropeanRoadAttributeId),
                       new AttributeId(snapshot.MaximumNationalRoadAttributeId),
                       new AttributeId(snapshot.MaximumNumberedRoadAttributeId),
                       new AttributeId(snapshot.MaximumLaneAttributeId),
                       new AttributeId(snapshot.MaximumWidthAttributeId),
                       new AttributeId(snapshot.MaximumSurfaceAttributeId),
                       snapshot.SegmentReusableLaneAttributeIdentifiers.ToImmutableDictionary(
                           segment => new RoadSegmentId(segment.SegmentId),
                           segment => (IReadOnlyList <AttributeId>)segment.ReusableAttributeIdentifiers
                           .Select(identifier => new AttributeId(identifier)).ToArray()),
                       snapshot.SegmentReusableWidthAttributeIdentifiers.ToImmutableDictionary(
                           segment => new RoadSegmentId(segment.SegmentId),
                           segment => (IReadOnlyList <AttributeId>)segment.ReusableAttributeIdentifiers
                           .Select(identifier => new AttributeId(identifier)).ToArray()),
                       snapshot.SegmentReusableSurfaceAttributeIdentifiers.ToImmutableDictionary(
                           segment => new RoadSegmentId(segment.SegmentId),
                           segment => (IReadOnlyList <AttributeId>)segment.ReusableAttributeIdentifiers
                           .Select(identifier => new AttributeId(identifier)).ToArray())
                       ));
        }