Skip to content

Commit

Permalink
implements connected node moved
Browse files Browse the repository at this point in the history
  • Loading branch information
runeanielsen committed Aug 5, 2020
1 parent eb22c51 commit ed4299c
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/OpenFTTH.GDBIntegrator.GeoDatabase/IGeoDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ public interface IGeoDatabase
Task<List<RouteNode>> GetIntersectingEndRouteNodes(RouteSegment routeSegment);
Task<List<RouteNode>> GetAllIntersectingRouteNodes(RouteSegment routeSegment);
Task<List<RouteNode>> GetAllIntersectingRouteNodesNotIncludingEdges(RouteSegment routeSegment);
Task<List<RouteNode>> GetAllIntersectingRouteNodesNotIncludingEdges(byte[] coordinates, Guid mrid);
Task<List<RouteNode>> GetIntersectingRouteNodes(RouteNode routeNode);
Task<List<RouteSegment>> GetIntersectingRouteSegments(RouteNode routeNode);
Task<List<RouteSegment>> GetIntersectingRouteSegments(byte[] coordinates);
Task<List<RouteSegment>> GetIntersectingRouteSegments(RouteNode routeNode, RouteSegment notInclude);
Task<List<RouteSegment>> GetIntersectingStartRouteSegments(RouteSegment routeSegment);
Task<List<RouteSegment>> GetIntersectingEndRouteSegments(RouteSegment routeSegment);
Expand Down
53 changes: 52 additions & 1 deletion src/OpenFTTH.GDBIntegrator.GeoDatabase/Postgres/Postgis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,25 @@ WHERE ST_Intersects(
}
}

public async Task<List<RouteSegment>> GetIntersectingRouteSegments(byte[] coordinates)
{
using (var connection = GetNpgsqlConnection())
{
var query = @"SELECT ST_AsBinary(coord) AS coord, mrid FROM route_network_integrator.route_segment
WHERE ST_Intersects(
ST_Buffer(
ST_GeomFromWKB(@coordinates, 25832),
@tolerance
),
coord) AND marked_to_be_deleted = false";

await connection.OpenAsync();
var result = await connection.QueryAsync<RouteSegment>(query, new { coordinates, tolerance = _applicationSettings.Tolerance });

return result.AsList();
}
}

public async Task<List<RouteSegment>> GetIntersectingRouteSegments(RouteNode routeNode, RouteSegment notInclude)
{
using (var connection = GetNpgsqlConnection())
Expand Down Expand Up @@ -195,7 +214,7 @@ AND NOT ST_Intersects(
(SELECT coord FROM route_network_integrator.route_segment
WHERE mrid = @mrid)
),
@tolerance),
@tolerance),
coord)";

await connection.OpenAsync();
Expand All @@ -205,6 +224,38 @@ AND NOT ST_Intersects(
}
}

public async Task<List<RouteNode>> GetAllIntersectingRouteNodesNotIncludingEdges(byte[] coordinates, Guid mrid)
{
using (var connection = GetNpgsqlConnection())
{
var query = @"
SELECT ST_Asbinary(coord) AS coord, mrid FROM route_network_integrator.route_node
WHERE ST_Intersects(
ST_Buffer(
ST_GeomFromWKB(@coordinates, 25832),
@tolerance),
coord)
AND marked_to_be_deleted = false
AND NOT ST_Intersects(
ST_Buffer(
ST_StartPoint(
ST_GeomFromWKB(@coordinates, 25832)),
@tolerance),
coord)
AND NOT ST_Intersects(
ST_Buffer(
ST_EndPoint(
ST_GeomFromWKB(@coordinates, 25832)),
@tolerance),
coord)";

await connection.OpenAsync();
var result = await connection.QueryAsync<RouteNode>(query, new { mrid, coordinates, _applicationSettings.Tolerance });

return result.AsList();
}
}

public async Task<List<RouteNode>> GetIntersectingRouteNodes(RouteNode routeNode)
{
using (var connection = GetNpgsqlConnection())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public async Task<INotification> CreateUpdatedEvent(RouteNode before, RouteNode
if (after.MarkAsDeleted)
return new RouteNodeDeleted { CmdId = cmdId, RouteNode = after };

return new RouteNodeLocationChanged { CmdId = cmdId, RouteNode = after };
return new RouteNodeLocationChanged { CmdId = cmdId, RouteNodeAfter = after, RouteNodeBefore = before };
}

public async Task<INotification> CreateDigitizedEvent(RouteNode routeNode)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
using OpenFTTH.GDBIntegrator.RouteNetwork;
using OpenFTTH.GDBIntegrator.Config;
using OpenFTTH.GDBIntegrator.Producer;
using OpenFTTH.GDBIntegrator.GeoDatabase;
using MediatR;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NetTopologySuite.Geometries;

namespace OpenFTTH.GDBIntegrator.Integrator.Notifications
{
public class RouteNodeLocationChanged : INotification
{
public RouteNode RouteNode { get; set; }
public RouteNode RouteNodeBefore { get; set; }
public RouteNode RouteNodeAfter { get; set; }
public Guid CmdId { get; set; }
}

Expand All @@ -21,29 +26,85 @@ public class RouteNodeLocationChangedHandler : INotificationHandler<RouteNodeLoc
private readonly ILogger<RouteNodeAddedHandler> _logger;
private readonly KafkaSetting _kafkaSettings;
private readonly IProducer _producer;
private readonly IGeoDatabase _geoDatabase;
private readonly IMediator _mediator;

public RouteNodeLocationChangedHandler(
ILogger<RouteNodeAddedHandler> logger,
IOptions<KafkaSetting> kafkaSettings,
IProducer producer)
IProducer producer,
IGeoDatabase geoDatabase,
IMediator mediator)
{
_logger = logger;
_kafkaSettings = kafkaSettings.Value;
_producer = producer;
_geoDatabase = geoDatabase;
}

public async Task Handle(RouteNodeLocationChanged request, CancellationToken token)
{
_logger.LogInformation($"Sending {nameof(RouteNodeLocationChanged)} with mrid '{request.RouteNode.Mrid}' to producer");
var intersectingSegmentsBeforeChange = (await _geoDatabase.GetIntersectingRouteSegments(request.RouteNodeBefore.Coord)).ToList();
var routeSegmentsToBeUpdated = new List<RouteSegment>();
if (intersectingSegmentsBeforeChange.Count > 0)
{
var anySegmentIntersectRouteNode = false;
foreach (var intersectingSegment in intersectingSegmentsBeforeChange)
{
var startNode = (await _geoDatabase.GetIntersectingStartRouteNodes(intersectingSegment)).FirstOrDefault();

if (startNode is null)
{
var lineString = intersectingSegment.GetLineString();
lineString.Coordinates[0] = new Coordinate(request.RouteNodeAfter.GetPoint().Coordinate);
intersectingSegment.Coord = lineString.AsBinary();
}
else
{
var lineString = intersectingSegment.GetLineString();
lineString.Coordinates[lineString.Coordinates.Count() - 1] = new Coordinate(request.RouteNodeAfter.GetPoint().Coordinate);
intersectingSegment.Coord = lineString.AsBinary();
}

anySegmentIntersectRouteNode = (await _geoDatabase.GetAllIntersectingRouteNodesNotIncludingEdges(intersectingSegment.Coord, intersectingSegment.Mrid)).Any();
if (anySegmentIntersectRouteNode)
break;

routeSegmentsToBeUpdated.Add(intersectingSegment);
}

// Rollback in case of segment intersecting with any route nodes
if (anySegmentIntersectRouteNode)
{
await _mediator.Publish(new RollbackInvalidRouteNodeOperation(request.RouteNodeBefore));
return;
}
}

_logger.LogInformation($"Sending {nameof(EventMessages.RouteNodeGeometryModified)} with mrid '{request.RouteNodeAfter.Mrid}' to producer");
await _producer.Produce(_kafkaSettings.EventRouteNetworkTopicName,
new EventMessages.RouteNodeGeometryModified
(
request.CmdId,
request.RouteNode.Mrid,
nameof(RouteNodeLocationChanged),
request.RouteNode.GetGeoJsonCoordinate()
));
new EventMessages.RouteNodeGeometryModified
(
request.CmdId,
request.RouteNodeAfter.Mrid,
nameof(RouteNodeLocationChanged),
request.RouteNodeAfter.GetGeoJsonCoordinate()
));

foreach (var routeSegmentToBeUpdated in routeSegmentsToBeUpdated)
{
await _geoDatabase.UpdateRouteSegment(routeSegmentToBeUpdated);

_logger.LogInformation($"Sending {nameof(EventMessages.RouteSegmentGeometryModified)} with mrid '{routeSegmentToBeUpdated.Mrid}' to producer");
await _producer.Produce(_kafkaSettings.EventRouteNetworkTopicName,
new EventMessages.RouteSegmentGeometryModified
(
request.CmdId,
routeSegmentToBeUpdated.Mrid,
nameof(RouteNodeLocationChanged),
routeSegmentToBeUpdated.GetGeoJsonCoordinate()
));
}
}
}
}
7 changes: 7 additions & 0 deletions src/OpenFTTH.GDBIntegrator.RouteNetwork/RouteNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ public RouteNode(Guid mrid, byte[] coord, Guid workTaskMrid, string username, st
MarkAsDeleted = markedAsDeleted;
}

public virtual Point GetPoint()
{
var wkbReader = new WKBReader();
var geometry = wkbReader.Read(Coord);
return (Point)geometry;
}

public virtual string GetGeoJsonCoordinate()
{
var wkbReader = new WKBReader();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ public async Task CreateUpdatedEvent_ShouldReturnRouteNodeLocationChanged_OnRout
using (var scope = new AssertionScope())
{
result.Should().BeOfType(typeof(RouteNodeLocationChanged));
result.RouteNode.Should().Be(afterNode);
result.RouteNodeAfter.Should().Be(afterNode);
result.CmdId.Should().NotBeEmpty();
}
}
Expand Down

0 comments on commit ed4299c

Please sign in to comment.