@@ -644,6 +644,7 @@ export class Fms<ID extends string = any> {
644644 let approachRnavTypeFlags : RnavTypeFlags = RnavTypeFlags . None ;
645645 let approachIsCircling = false ;
646646 let approachIsVtf = false ;
647+ let approachIsRnpAr = false ;
647648 let referenceFacility : VorFacility | null = null ;
648649 let approachRunway : OneWayRunway | null = null ;
649650
@@ -667,6 +668,7 @@ export class Fms<ID extends string = any> {
667668 approachRnavTypeFlags = approach . rnavTypeFlags ;
668669 approachIsCircling = ! approach . runway ;
669670 approachIsVtf = plan . procedureDetails . approachTransitionIndex < 0 ;
671+ approachIsRnpAr = ApproachUtils . isRnpAr ( approach ) ;
670672 if ( FmsUtils . approachHasNavFrequency ( approach ) ) {
671673 referenceFacility = ( await ApproachUtils . getReferenceFacility ( approach , this . facLoader ) as VorFacility | undefined ) ?? null ;
672674 }
@@ -697,7 +699,18 @@ export class Fms<ID extends string = any> {
697699 }
698700 }
699701
700- this . setApproachDetails ( false , approachLoaded , approachType , approachRnavType , approachRnavTypeFlags , approachIsCircling , approachIsVtf , referenceFacility , approachRunway ) ;
702+ this . setApproachDetails (
703+ false ,
704+ approachLoaded ,
705+ approachType ,
706+ approachRnavType ,
707+ approachRnavTypeFlags ,
708+ approachIsCircling ,
709+ approachIsVtf ,
710+ approachIsRnpAr ,
711+ referenceFacility ,
712+ approachRunway ,
713+ ) ;
701714 }
702715
703716 /**
@@ -1456,7 +1469,7 @@ export class Fms<ID extends string = any> {
14561469 }
14571470
14581471 ++ this . updateApproachDetailsOpId ;
1459- this . setApproachDetails ( true , false , ApproachType . APPROACH_TYPE_UNKNOWN , RnavTypeFlags . None , RnavTypeFlags . None , false , false , null , null ) ;
1472+ this . setApproachDetails ( true , false , ApproachType . APPROACH_TYPE_UNKNOWN , RnavTypeFlags . None , RnavTypeFlags . None , false , false , false , null , null ) ;
14601473 plan . deleteUserData ( Fms . VTF_FAF_DATA_KEY ) ;
14611474
14621475 plan . calculate ( 0 ) ;
@@ -2105,19 +2118,21 @@ export class Fms<ID extends string = any> {
21052118 }
21062119 }
21072120
2108- const approachType = visualRunway ? AdditionalApproachType . APPROACH_TYPE_VISUAL : facility . approaches [ approachIndex ] . approachType ;
2109- const bestRnavType = visualRunway ? RnavTypeFlags . None : FmsUtils . getBestRnavType ( facility . approaches [ approachIndex ] . rnavTypeFlags ) ;
2110- const rnavTypeFlags = visualRunway ? RnavTypeFlags . None : facility . approaches [ approachIndex ] . rnavTypeFlags ;
2111- const approachIsCircling = ! visualRunway && ! facility . approaches [ approachIndex ] . runway ? true : false ;
2121+ const approach = facility . approaches [ approachIndex ] ;
2122+ const approachType = visualRunway ? AdditionalApproachType . APPROACH_TYPE_VISUAL : approach . approachType ;
2123+ const bestRnavType = visualRunway ? RnavTypeFlags . None : FmsUtils . getBestRnavType ( approach . rnavTypeFlags ) ;
2124+ const rnavTypeFlags = visualRunway ? RnavTypeFlags . None : approach . rnavTypeFlags ;
2125+ const approachIsCircling = ! visualRunway && ! approach . runway ? true : false ;
21122126 const isVtf = approachTransitionIndex < 0 ;
2127+ const isRnpAr = visualRunway ? false : ApproachUtils . isRnpAr ( approach ) ;
21132128
21142129 let referenceFacility : VorFacility | null = null ;
2115- if ( ! visualRunway && FmsUtils . approachHasNavFrequency ( facility . approaches [ approachIndex ] ) ) {
2116- referenceFacility = ( await ApproachUtils . getReferenceFacility ( facility . approaches [ approachIndex ] , this . facLoader ) as VorFacility | undefined ) ?? null ;
2130+ if ( ! visualRunway && FmsUtils . approachHasNavFrequency ( approach ) ) {
2131+ referenceFacility = ( await ApproachUtils . getReferenceFacility ( approach , this . facLoader ) as VorFacility | undefined ) ?? null ;
21172132 }
21182133
21192134 ++ this . updateApproachDetailsOpId ;
2120- this . setApproachDetails ( true , true , approachType , bestRnavType , rnavTypeFlags , approachIsCircling , isVtf , referenceFacility , approachRunway ) ;
2135+ this . setApproachDetails ( true , true , approachType , bestRnavType , rnavTypeFlags , approachIsCircling , isVtf , isRnpAr , referenceFacility , approachRunway ) ;
21212136
21222137 this . autoDesignateProcedureConstraints ( plan , approachSegment . segmentIndex ) ;
21232138
@@ -2187,6 +2202,8 @@ export class Fms<ID extends string = any> {
21872202 ? FmsUtils . buildVisualApproach ( facility , visualRunway ! , this . visualApproachOptions . finalFixDistance , this . visualApproachOptions . strghtFixDistance )
21882203 : facility . approaches [ approachIndex ] ;
21892204
2205+ const finalLegs = approach . finalLegs ;
2206+
21902207 const transition = approach . transitions [ approachTransitionIndex ] ;
21912208 const isVtf = approachTransitionIndex < 0 ;
21922209 const insertProcedureObject : InsertProcedureObject = { procedureLegs : [ ] } ;
@@ -2200,14 +2217,33 @@ export class Fms<ID extends string = any> {
22002217 }
22012218 }
22022219
2203- const lastTransitionLeg = insertProcedureObject . procedureLegs [ insertProcedureObject . procedureLegs . length - 1 ] ;
2220+ const lastTransitionLeg = insertProcedureObject . procedureLegs [ insertProcedureObject . procedureLegs . length - 1 ] as InsertProcedureObjectLeg | undefined ;
2221+
2222+ let finalLegsStartIndex = 0 ;
22042223
22052224 if ( isVtf ) {
22062225 insertProcedureObject . procedureLegs . push ( FlightPlan . createLeg ( { type : LegType . ThruDiscontinuity } ) ) ;
2226+ } else if ( lastTransitionLeg ) {
2227+ // Check if the last transition leg is an XF leg that terminates at the FACF (flagged as IF) or FAF. If so, then
2228+ // we need to merge the last transition leg with the FACF/FAF leg and skip every leg in the final legs array
2229+ // before the latter.
2230+ if ( FlightPlanUtils . isToFixLeg ( lastTransitionLeg . type ) && ! ICAO . isValueEmpty ( lastTransitionLeg . fixIcaoStruct ) ) {
2231+ for ( let i = 0 ; i < finalLegs . length ; i ++ ) {
2232+ const leg = finalLegs [ i ] ;
2233+ if (
2234+ BitFlags . isAny ( leg . fixTypeFlags , FixTypeFlags . IF | FixTypeFlags . FAF )
2235+ && FlightPlanUtils . isToFixLeg ( leg . type )
2236+ && ICAO . valueEquals ( leg . fixIcaoStruct , lastTransitionLeg . fixIcaoStruct )
2237+ ) {
2238+ insertProcedureObject . procedureLegs [ insertProcedureObject . procedureLegs . length - 1 ] = this . mergeDuplicateLegData ( lastTransitionLeg , leg ) ;
2239+ finalLegsStartIndex = i + 1 ;
2240+ break ;
2241+ }
2242+ }
2243+ }
22072244 }
22082245
2209- const finalLegs = approach . finalLegs ;
2210- for ( let i = 0 ; i < finalLegs . length ; i ++ ) {
2246+ for ( let i = finalLegsStartIndex ; i < finalLegs . length ; i ++ ) {
22112247 const leg = FlightPlanUtils . convertLegRunwayIcaosToSdkFormat ( FlightPlan . createLeg ( finalLegs [ i ] ) ) ;
22122248 if ( i === 0 && lastTransitionLeg && this . isDuplicateIFLeg ( lastTransitionLeg , leg ) ) {
22132249 insertProcedureObject . procedureLegs [ insertProcedureObject . procedureLegs . length - 1 ] = this . mergeDuplicateLegData ( lastTransitionLeg , leg ) ;
@@ -2425,7 +2461,7 @@ export class Fms<ID extends string = any> {
24252461 }
24262462
24272463 ++ this . updateApproachDetailsOpId ;
2428- this . setApproachDetails ( true , true , approachType , bestRnavType , rnavTypeFlags , approachIsCircling , isVtf , referenceFacility , approachRunway ) ;
2464+ this . setApproachDetails ( true , true , approachType , bestRnavType , rnavTypeFlags , approachIsCircling , isVtf , false , referenceFacility , approachRunway ) ;
24292465
24302466 await plan . calculate ( ) ;
24312467
@@ -3347,7 +3383,7 @@ export class Fms<ID extends string = any> {
33473383 const plan = this . getFlightPlan ( ) ;
33483384
33493385 ++ this . updateApproachDetailsOpId ;
3350- this . setApproachDetails ( true , false , ApproachType . APPROACH_TYPE_UNKNOWN , RnavTypeFlags . None , RnavTypeFlags . None , false , false , null , null ) ;
3386+ this . setApproachDetails ( true , false , ApproachType . APPROACH_TYPE_UNKNOWN , RnavTypeFlags . None , RnavTypeFlags . None , false , false , false , null , null ) ;
33513387 plan . deleteUserData ( Fms . VTF_FAF_DATA_KEY ) ;
33523388
33533389 const hasArrival = plan . procedureDetails . arrivalIndex >= 0 ;
@@ -4264,7 +4300,7 @@ export class Fms<ID extends string = any> {
42644300 plan . deleteUserData ( FmsFplUserDataKey . ApproachSkipCourseReversal ) ;
42654301
42664302 ++ this . updateApproachDetailsOpId ;
4267- this . setApproachDetails ( true , false , ApproachType . APPROACH_TYPE_UNKNOWN , RnavTypeFlags . None , RnavTypeFlags . None , false , false , null , null ) ;
4303+ this . setApproachDetails ( true , false , ApproachType . APPROACH_TYPE_UNKNOWN , RnavTypeFlags . None , RnavTypeFlags . None , false , false , false , null , null ) ;
42684304 plan . deleteUserData ( Fms . VTF_FAF_DATA_KEY ) ;
42694305
42704306 plan . setCalculatingLeg ( 0 ) ;
@@ -5941,18 +5977,32 @@ export class Fms<ID extends string = any> {
59415977 }
59425978
59435979 /**
5944- * Merges two duplicate legs such that the new merged leg contains the fix type and altitude data from the source leg
5945- * and all other data is derived from the target leg.
5980+ * Merges two duplicate legs. The merged leg will be identical to the target leg with the following exceptions:
5981+ * - The merged leg's fix type flags are the union of those of the target and source legs.
5982+ * - The merged leg's altitude restriction data are equal to those of the source leg if the source leg defines an
5983+ * altitude restriction. Otherwise the merged leg's altitude restriction data are equal to those of the target leg.
5984+ * - The merged leg's speed restriction data are equal to those of the source leg if the source leg defines a speed
5985+ * restriction. Otherwise the merged leg's speed restriction data are equal to those of the target leg.
59465986 * @param target The target leg.
59475987 * @param source The source leg.
5948- * @returns the merged leg.
5988+ * @returns The merged leg.
59495989 */
59505990 private mergeDuplicateLegData ( target : FlightPlanLeg , source : FlightPlanLeg ) : FlightPlanLeg {
59515991 const merged = FlightPlan . createLeg ( target ) ;
5992+
59525993 merged . fixTypeFlags |= source . fixTypeFlags ;
5953- merged . altDesc = source . altDesc ;
5954- merged . altitude1 = source . altitude1 ;
5955- merged . altitude2 = source . altitude2 ;
5994+
5995+ if ( source . altDesc !== AltitudeRestrictionType . Unused ) {
5996+ merged . altDesc = source . altDesc ;
5997+ merged . altitude1 = source . altitude1 ;
5998+ merged . altitude2 = source . altitude2 ;
5999+ }
6000+
6001+ if ( source . speedRestrictionDesc !== SpeedRestrictionType . Unused ) {
6002+ merged . speedRestrictionDesc = source . speedRestrictionDesc ;
6003+ merged . speedRestriction = source . speedRestriction ;
6004+ }
6005+
59566006 return merged ;
59576007 }
59586008
@@ -6165,6 +6215,7 @@ export class Fms<ID extends string = any> {
61656215 * @param rnavTypeFlags The RNAV minimum type flags for the approach.
61666216 * @param isCircling Whether the approach is a circling approach.
61676217 * @param isVtf Whether the approach is a vectors-to-final approach.
6218+ * @param isRnpAr Whether the approach is an RNP-AR approach.
61686219 * @param referenceFacility The approach's reference facility.
61696220 * @param runway The assigned runway for the approach
61706221 */
@@ -6176,6 +6227,7 @@ export class Fms<ID extends string = any> {
61766227 rnavTypeFlags ?: RnavTypeFlags ,
61776228 isCircling ?: boolean ,
61786229 isVtf ?: boolean ,
6230+ isRnpAr ?: boolean ,
61796231 referenceFacility ?: VorFacility | null ,
61806232 runway ?: OneWayRunway | null
61816233 ) : void {
@@ -6185,14 +6237,12 @@ export class Fms<ID extends string = any> {
61856237 rnavTypeFlags !== undefined && this . approachDetails . set ( 'rnavTypeFlags' , rnavTypeFlags ) ;
61866238 isCircling !== undefined && this . approachDetails . set ( 'isCircling' , isCircling ) ;
61876239 isVtf !== undefined && this . approachDetails . set ( 'isVtf' , isVtf ) ;
6240+ isRnpAr !== undefined && this . approachDetails . set ( 'isRnpAr' , isRnpAr ) ;
61886241 referenceFacility !== undefined && this . approachDetails . set ( 'referenceFacility' , referenceFacility ) ;
61896242 runway !== undefined && this . approachDetails . set ( 'runway' , runway ) ;
61906243
61916244 const approachDetails = this . approachDetails . get ( ) ;
61926245
6193- // If an approach is flagged as RNAV but has no defined RNAV minima, assume it is an RNP (AR) approach if it is not circling.
6194- this . approachDetails . set ( 'isRnpAr' , approachDetails . type === ApproachType . APPROACH_TYPE_RNAV && approachDetails . bestRnavType === 0 && ! approachDetails . isCircling ) ;
6195-
61966246 if ( this . needPublishApproachDetails ) {
61976247 this . needPublishApproachDetails = false ;
61986248
0 commit comments