6
6
using System . Collections . Generic ;
7
7
using System . Linq ;
8
8
using System . Threading . Tasks ;
9
-
9
+ using GJFeature = GeoJSON . Net . Feature ; // use an alias since Feature exists in HttpClients.Models
10
10
namespace Hmcr . Domain . Services
11
11
{
12
12
public interface ISpatialService
@@ -19,17 +19,14 @@ public interface ISpatialService
19
19
( decimal offset , string rfiSegment , string rfiSegmentName , string thresholdLevel , Dictionary < string , List < string > > errors ) ;
20
20
Task < ( SpValidationResult result , decimal snappedStartOffset , decimal snappedEndOffset , Point startPoint , Point endPoint , List < Line > lines , RfiSegment rfiSegment ) >
21
21
ValidateLrsLineAsync ( decimal startOffset , decimal endOffset , string rfiSegment , string rfiSegmentName , string thresholdLevel , Dictionary < string , List < string > > errors ) ;
22
- Task < ( SpValidationResult result , List < SurfaceType > surfaceTypes ) > GetSurfaceTypeAssocWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
23
- Task < ( SpValidationResult result , SurfaceType surfaceType ) > GetSurfaceTypeAssocWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
24
- Task < ( SpValidationResult result , List < MaintenanceClass > maintenanceClasses ) > GetMaintenanceClassAssocWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
25
- Task < ( SpValidationResult result , MaintenanceClass maintenanceClass ) > GetMaintenanceClassAssocWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
22
+
26
23
Task < ( SpValidationResult result , List < Structure > structures ) > GetStructuresOnRFISegmentAsync ( string rfiSegmentName , string recordNumber ) ;
27
- Task < ( SpValidationResult result , HighwayProfile highwayProfile ) > GetHighwayProfileAssocWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
28
- Task < ( SpValidationResult result , List < HighwayProfile > highwayProfiles ) > GetHighwayProfileAssocWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
29
- Task < ( SpValidationResult result , List < Guardrail > guardrails ) > GetGuardrailAssociatedWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
30
- Task < ( SpValidationResult result , Guardrail guardrail ) > GetGuardrailAssociatedWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber ) ;
31
24
Task < ( SpValidationResult result , List < RestArea > restAreas ) > GetRestAreasOnRFISegmentAsync ( string rfiSegmentName , string recordNumber ) ;
32
25
26
+ Task < ( SpValidationResult result , string message , List < SurfaceType > surfaceTypes ) > GetSurfaceTypesAssocWithRFISegment ( string rfiSegmentName , string recordNumber , decimal startOffset , decimal endOffset ) ;
27
+ Task < ( SpValidationResult result , string message , List < MaintenanceClass > maintenanceClasses ) > GetMaintenanceClassAssocWithRFISegment ( string rfiSegmentName , string recordNumber , decimal startOffset , decimal endOffset ) ;
28
+ Task < ( SpValidationResult result , string message , List < HighwayProfile > highwayProfiles ) > GetHighwayProfileAssocWithRFISegment ( string rfiSegmentName , string recordNumber , decimal startOffset , decimal endOffset ) ;
29
+ Task < ( SpValidationResult result , string message , List < Guardrail > guardrails ) > GetGuardrailsAssocWithRFISegment ( string rfiSegmentName , string recordNumber , decimal startOffset , decimal endOffset ) ;
33
30
}
34
31
35
32
public class SpatialService : ISpatialService
@@ -254,67 +251,193 @@ public SpatialService(IOasApi oasApi, IFieldValidatorService validator, ILookupC
254
251
return ( SpValidationResult . Success , rfiDetail ) ;
255
252
}
256
253
257
- public async Task < ( SpValidationResult result , List < SurfaceType > surfaceTypes ) > GetSurfaceTypeAssocWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
254
+ public async Task < ( SpValidationResult result , string message , List < SurfaceType > surfaceTypes ) > GetSurfaceTypesAssocWithRFISegment ( string rfiSegmentName , string recordNumber ,
255
+ decimal startOffset , decimal endOffset )
258
256
{
259
- var surfaceTypes = await _inventoryApi . GetSurfaceTypeAssociatedWithLine ( geometry , recordNumber ) ;
257
+ var surfaceTypes = new List < SurfaceType > ( ) ;
258
+ var validationResult = SpValidationResult . Success ;
260
259
261
- return ( SpValidationResult . Success , surfaceTypes ) ;
262
- }
260
+ //retrieve the feature collection for the highway unique from the ogs endpoint
261
+ var ( featureCollection , errorMsg ) = await _inventoryApi . GetSurfaceType ( rfiSegmentName , recordNumber ) ;
262
+
263
+ var foundFeatures = FindFeaturesWithinSegment ( featureCollection , startOffset , endOffset ) ;
263
264
264
- public async Task < ( SpValidationResult result , SurfaceType surfaceType ) > GetSurfaceTypeAssocWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
265
- {
266
- var surfaceType = await _inventoryApi . GetSurfaceTypeAssociatedWithPoint ( geometry , recordNumber ) ;
265
+ if ( foundFeatures . Features . Count > 0 )
266
+ {
267
+ foreach ( var feature in foundFeatures . Features )
268
+ {
269
+ SurfaceType surfaceType = new SurfaceType ( ) ;
270
+ surfaceType . Length = ( double ) feature . Properties [ "LENGTH_KM" ] ;
271
+ surfaceType . Type = ( string ) feature . Properties [ "SURFACE_TYPE" ] ;
272
+ surfaceTypes . Add ( surfaceType ) ;
273
+ }
274
+ }
275
+ else
276
+ {
277
+ if ( errorMsg . Length > 0 )
278
+ validationResult = SpValidationResult . Fail ;
279
+ }
267
280
268
- return ( SpValidationResult . Success , surfaceType ) ;
281
+ return ( validationResult , errorMsg , surfaceTypes ) ;
269
282
}
270
283
271
- public async Task < ( SpValidationResult result , MaintenanceClass maintenanceClass ) > GetMaintenanceClassAssocWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
284
+ public async Task < ( SpValidationResult result , string message , List < MaintenanceClass > maintenanceClasses ) > GetMaintenanceClassAssocWithRFISegment ( string rfiSegmentName , string recordNumber ,
285
+ decimal startOffset , decimal endOffset )
272
286
{
273
- var maintenanceClass = await _inventoryApi . GetMaintenanceClassesAssociatedWithPoint ( geometry , recordNumber ) ;
287
+ var maintenanceClasses = new List < MaintenanceClass > ( ) ;
288
+ var validationResult = SpValidationResult . Success ;
289
+
290
+ var ( featureCollection , errorMsg ) = await _inventoryApi . GetMaintenanceClass ( rfiSegmentName , recordNumber ) ;
291
+
292
+ var foundFeatures = FindFeaturesWithinSegment ( featureCollection , startOffset , endOffset ) ;
293
+
294
+ if ( foundFeatures != null )
295
+ {
296
+ foreach ( var feature in foundFeatures . Features )
297
+ {
298
+ MaintenanceClass maintenanceClass = new MaintenanceClass ( ) ;
299
+ maintenanceClass . Length = ( double ) feature . Properties [ "LENGTH_KM" ] ;
300
+ maintenanceClass . SummerRating = ( string ) feature . Properties [ "SUMMER_CLASS_RATING" ] ;
301
+ maintenanceClass . WinterRating = ( string ) feature . Properties [ "WINTER_CLASS_RATING" ] ;
302
+
303
+ maintenanceClasses . Add ( maintenanceClass ) ;
304
+ }
305
+ }
306
+ else
307
+ {
308
+ if ( errorMsg . Length > 0 )
309
+ validationResult = SpValidationResult . Fail ;
310
+ }
274
311
275
- return ( SpValidationResult . Success , maintenanceClass ) ;
312
+ return ( validationResult , errorMsg , maintenanceClasses ) ;
276
313
}
277
314
278
- public async Task < ( SpValidationResult result , List < MaintenanceClass > maintenanceClasses ) > GetMaintenanceClassAssocWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
315
+ public async Task < ( SpValidationResult result , string message , List < HighwayProfile > highwayProfiles ) > GetHighwayProfileAssocWithRFISegment ( string rfiSegmentName , string recordNumber ,
316
+ decimal startOffset , decimal endOffset )
279
317
{
280
- var maintenanceClasses = await _inventoryApi . GetMaintenanceClassesAssociatedWithLine ( geometry , recordNumber ) ;
318
+ var highwayProfiles = new List < HighwayProfile > ( ) ;
319
+ var validationResult = SpValidationResult . Success ;
281
320
282
- return ( SpValidationResult . Success , maintenanceClasses ) ;
283
- }
321
+ var ( featureCollection , errorMsg ) = await _inventoryApi . GetHighwayProfile ( rfiSegmentName , recordNumber ) ;
284
322
285
- public async Task < ( SpValidationResult result , List < Structure > structures ) > GetStructuresOnRFISegmentAsync ( string rfiSegmentName , string recordNumber )
286
- {
287
- var structures = await _inventoryApi . GetStructuresOnRFISegment ( rfiSegmentName , recordNumber ) ;
323
+ var foundFeatures = FindFeaturesWithinSegment ( featureCollection , startOffset , endOffset ) ;
288
324
289
- return ( SpValidationResult . Success , structures ) ;
325
+ if ( foundFeatures . Features . Count > 0 )
326
+ {
327
+ foreach ( var feature in foundFeatures . Features )
328
+ {
329
+ HighwayProfile highwayProfile = new HighwayProfile ( ) ;
330
+ highwayProfile . Length = ( double ) feature . Properties [ "LENGTH_KM" ] ;
331
+ highwayProfile . NumberOfLanes = Convert . ToInt32 ( feature . Properties [ "NUMBER_OF_LANES" ] ) ;
332
+ highwayProfile . DividedHighwayFlag = ( string ) feature . Properties [ "DIVIDED_HIGHWAY_FLAG" ] ;
333
+
334
+ highwayProfiles . Add ( highwayProfile ) ;
335
+ }
336
+ }
337
+ else
338
+ {
339
+ if ( errorMsg . Length > 0 )
340
+ validationResult = SpValidationResult . Fail ;
341
+ }
342
+
343
+ return ( validationResult , errorMsg , highwayProfiles ) ;
290
344
}
291
345
292
- public async Task < ( SpValidationResult result , List < HighwayProfile > highwayProfiles ) > GetHighwayProfileAssocWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
346
+ public async Task < ( SpValidationResult result , string message , List < Guardrail > guardrails ) > GetGuardrailsAssocWithRFISegment ( string rfiSegmentName , string recordNumber ,
347
+ decimal startOffset , decimal endOffset )
293
348
{
294
- var highwayProfiles = await _inventoryApi . GetHighwayProfileAssociatedWithLine ( geometry , recordNumber ) ;
349
+ var guardrails = new List < Guardrail > ( ) ;
350
+ var validationResult = SpValidationResult . Success ;
351
+
352
+ var ( featureCollection , errorMsg ) = await _inventoryApi . GetGuardrail ( rfiSegmentName , recordNumber ) ;
353
+
354
+ var foundFeatures = FindFeaturesWithinSegment ( featureCollection , startOffset , endOffset ) ;
295
355
296
- return ( SpValidationResult . Success , highwayProfiles ) ;
356
+ if ( foundFeatures . Features . Count > 0 )
357
+ {
358
+ foreach ( var feature in foundFeatures . Features )
359
+ {
360
+ Guardrail guardrail = new Guardrail ( ) ;
361
+ guardrail . Length = ( double ) feature . Properties [ "LENGTH_KM" ] ;
362
+ guardrail . GuardrailType = ( string ) feature . Properties [ "GUARDRAIL_TYPE" ] ;
363
+
364
+ guardrails . Add ( guardrail ) ;
365
+ }
366
+ }
367
+ else
368
+ {
369
+ if ( errorMsg . Length > 0 )
370
+ validationResult = SpValidationResult . Fail ;
371
+ }
372
+
373
+ return ( validationResult , errorMsg , guardrails ) ;
297
374
}
298
375
299
- public async Task < ( SpValidationResult result , HighwayProfile highwayProfile ) > GetHighwayProfileAssocWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
376
+
377
+ private GJFeature . FeatureCollection FindFeaturesWithinSegment ( GJFeature . FeatureCollection featureCollection , decimal startOffset , decimal endOffset )
300
378
{
301
- var highwayProfile = await _inventoryApi . GetHighwayProfileAssociatedWithPoint ( geometry , recordNumber ) ;
379
+ GJFeature . FeatureCollection foundFeatures = new GJFeature . FeatureCollection ( ) ;
302
380
303
- return ( SpValidationResult . Success , highwayProfile ) ;
381
+ if ( featureCollection != null )
382
+ {
383
+ //since we got the features for the entire highway we need to determine which ones actually fall within our offsets
384
+
385
+ //need to handle scenarios when the coordinates are 'backwards'
386
+ // to do this we'll set the end offset as the larger value and the start as the smaller
387
+ decimal adjStartOffset = ( startOffset > endOffset ) ? endOffset : startOffset ;
388
+ decimal adjEndOffset = ( startOffset > endOffset ) ? startOffset : endOffset ;
389
+
390
+ decimal newStartOffset = adjStartOffset ;
391
+
392
+ foreach ( var feature in featureCollection . Features )
393
+ {
394
+ //get the begin & end KM, have to use convert instead of explicit cast because of 0
395
+ var beginKM = Convert . ToDecimal ( feature . Properties [ "BEGIN_KM" ] ) ;
396
+ var endKM = Convert . ToDecimal ( feature . Properties [ "END_KM" ] ) ;
397
+
398
+ //it's in our range
399
+ if ( newStartOffset <= adjEndOffset )
400
+ {
401
+ if ( ( newStartOffset >= beginKM ) && ( newStartOffset <= endKM ) )
402
+ {
403
+ var lengthKM = GetAdjustedLengthKM ( adjStartOffset , adjEndOffset , beginKM , endKM , Convert . ToDecimal ( feature . Properties [ "LENGTH_KM" ] ) ) ;
404
+ newStartOffset += lengthKM ;
405
+
406
+ feature . Properties [ "LENGTH_KM" ] = ( double ) lengthKM ;
407
+
408
+ foundFeatures . Features . Add ( feature ) ;
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ return foundFeatures ;
304
415
}
305
416
306
- public async Task < ( SpValidationResult result , List < Guardrail > guardrails ) > GetGuardrailAssociatedWithLineAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
417
+ private decimal GetAdjustedLengthKM ( decimal startOffset , decimal endOffset , decimal beginKM , decimal endKM , decimal lengthKM )
307
418
{
308
- var guardrails = await _inventoryApi . GetGuardrailAssociatedWithLine ( geometry , recordNumber ) ;
419
+ //length needs to be adjusted to segment begin
420
+ if ( startOffset >= beginKM )
421
+ {
422
+ //don't let it go below zero
423
+ lengthKM -= Math . Max ( startOffset - beginKM , 0 ) ;
424
+ }
309
425
310
- return ( SpValidationResult . Success , guardrails ) ;
426
+ //length needs to be adjusted to segment end
427
+ if ( endOffset <= endKM )
428
+ {
429
+ lengthKM -= Math . Max ( endKM - endOffset , 0 ) ;
430
+ }
431
+
432
+ return lengthKM ;
311
433
}
312
434
313
- public async Task < ( SpValidationResult result , Guardrail guardrail ) > GetGuardrailAssociatedWithPointAsync ( NetTopologySuite . Geometries . Geometry geometry , string recordNumber )
435
+ public async Task < ( SpValidationResult result , List < Structure > structures ) > GetStructuresOnRFISegmentAsync ( string rfiSegmentName , string recordNumber )
314
436
{
315
- var guardrail = await _inventoryApi . GetGuardrailAssociatedWithPoint ( geometry , recordNumber ) ;
437
+ var structures = await _inventoryApi . GetStructuresOnRFISegment ( rfiSegmentName , recordNumber ) ;
438
+
316
439
317
- return ( SpValidationResult . Success , guardrail ) ;
440
+ return ( SpValidationResult . Success , structures ) ;
318
441
}
319
442
320
443
public async Task < ( SpValidationResult result , List < RestArea > restAreas ) > GetRestAreasOnRFISegmentAsync ( string rfiSegmentName , string recordNumber )
0 commit comments