@@ -51,6 +51,9 @@ const squaredDist = (pos1: Position, pos2: Position) => {
5151
5252const dist = ( pos1 : Position , pos2 : Position ) => Math . sqrt ( squaredDist ( pos1 , pos2 ) )
5353
54+ const isFinitePoint = ( point : Position | undefined | null ) : point is Position =>
55+ ! ! point && Number . isFinite ( point . x ) && Number . isFinite ( point . y ) ;
56+
5457const closestToAverage = ( positions : Position [ ] ) : Position => {
5558 const average = avg ( positions ) ;
5659 let closest = positions [ 0 ] ;
@@ -582,7 +585,7 @@ export class DiagramService {
582585 if ( equal ( from , reactionP ) || equal ( to , reactionP ) ) d -= REACTION_RADIUS ;
583586 if ( classes . includes ( 'positive-regulation' ) || classes . includes ( 'catalysis' ) || classes . includes ( 'production' ) ) d -= ARROW_MULT * T ;
584587 // console.assert(d > MIN_DIST, `The edge between reaction: R-HSA-${reaction.reactomeId} and entity: R-HSA-${node.reactomeId} in pathway ${id} has a visible length of ${d} which is shorter than ${MIN_DIST}`)
585- console . assert ( d > MIN_DIST , `${ id } \t${ diagram . displayName } \t${ hasFadeOut } \tR-HSA-${ reaction . reactomeId } \tR-HSA-${ node . reactomeId } \thttps://release.reactome.org/PathwayBrowser/#/${ id } &SEL=R-HSA-${ reaction . reactomeId } &FLG=R-HSA-${ node . reactomeId } \thttps://reactome-pwp.github.io/PathwayBrowser/${ id } ?select=${ reaction . reactomeId } &flag=${ node . reactomeId } ` )
588+ console . assert ( Math . abs ( d ) >= MIN_DIST , `${ id } \t${ diagram . displayName } \t${ hasFadeOut } \tR-HSA-${ reaction . reactomeId } \tR-HSA-${ node . reactomeId } \thttps://release.reactome.org/PathwayBrowser/#/${ id } &SEL=R-HSA-${ reaction . reactomeId } &FLG=R-HSA-${ node . reactomeId } \thttps://reactome-pwp.github.io/PathwayBrowser/${ id } ?select=${ reaction . reactomeId } &flag=${ node . reactomeId } ` )
586589
587590 let replacement , replacedBy ;
588591 if ( connector . isFadeOut ) {
@@ -595,23 +598,27 @@ export class DiagramService {
595598 }
596599 if ( ! connector . isFadeOut ) {
597600 // First case: same node is used both special and normal context
598- replacement = node . connectors . find ( otherConnector => otherConnector !== connector && otherConnector . isFadeOut && samePoint ( idToEdges . get ( otherConnector . edgeId ) ! . position , reaction . position ) ) ?. edgeId ;
601+ replacement = node . connectors . find ( otherConnector => {
602+ if ( otherConnector === connector || ! otherConnector . isFadeOut ) return false ;
603+ const otherEdge = idToEdges . get ( otherConnector . edgeId ) ;
604+ return samePoint ( otherEdge ?. position , reaction . position ) ;
605+ } ) ?. edgeId ;
599606 // console.log("Reaction edge", replacement)
600607
601608 // Second case: different nodes are used between special and normal context
602609 replacement = replacement || ( posToNormalNode . get ( pointToStr ( node . position ) ) && posToNormalEdge . get ( pointToStr ( reaction . position ) ) ) ?. id ;
603610 // console.log("Reaction edge", replacement)
604611
605612 }
613+ const relativeSegments = this . getRelativeSegmentsData ( relatives ) ;
606614 const edge : cytoscape . EdgeDefinition = {
607615 data : {
608616 id : this . getEdgeId ( source , connector , target , edgeIds ) ,
609617 graph : dbIdToGraphEdge . get ( reaction . reactomeId ) ,
610618 source : source . id + '' ,
611619 target : target . id + '' ,
612620 stoichiometry : connector . stoichiometry . value ,
613- weights : relatives . weights . join ( " " ) ,
614- distances : relatives . distances . join ( " " ) ,
621+ ...relativeSegments ,
615622 sourceEndpoint : this . endpoint ( sourceP , from ) ,
616623 targetEndpoint : this . endpoint ( targetP , to ) ,
617624 pathway : eventIdToSubPathwayId . get ( reaction . reactomeId ) ,
@@ -648,6 +655,7 @@ export class DiagramService {
648655
649656 // points = addRoundness(from, to, points);
650657 const relatives = this . absoluteToRelative ( from , to , points ) ;
658+ const relativeSegments = this . getRelativeSegmentsData ( relatives ) ;
651659
652660 const classes = [ ...this . linkClassMap . get ( link . renderableClass ) ! ] ;
653661 if ( link . isDisease ) classes . push ( 'disease' ) ;
@@ -660,8 +668,7 @@ export class DiagramService {
660668 id : link . id + '' ,
661669 source : link . inputs [ 0 ] . id + '' ,
662670 target : link . outputs [ 0 ] . id + '' ,
663- weights : relatives . weights . join ( " " ) ,
664- distances : relatives . distances . join ( " " ) ,
671+ ...relativeSegments ,
665672 sourceEndpoint : this . endpoint ( sourceP , from ) ,
666673 targetEndpoint : this . endpoint ( targetP , to ) ,
667674 isFadeOut : link . isFadeOut ,
@@ -746,6 +753,18 @@ export class DiagramService {
746753 return `${ point . x - source . x } ${ point . y - source . y } `
747754 }
748755
756+ private getRelativeSegmentsData ( relatives : RelativePosition ) : Partial < { weights : string , distances : string } > {
757+ const weights = relatives . weights . filter ( value => Number . isFinite ( value ) ) ;
758+ const distances = relatives . distances . filter ( value => Number . isFinite ( value ) ) ;
759+ if ( weights . length === 0 || distances . length === 0 || weights . length !== distances . length ) {
760+ return { } ;
761+ }
762+ return {
763+ weights : weights . join ( " " ) ,
764+ distances : distances . join ( " " ) ,
765+ } ;
766+ }
767+
749768
750769 /**
751770 * Use Matrix power to convert points from an absolute coordinate system to an edge relative system
@@ -761,19 +780,26 @@ export class DiagramService {
761780 const relatives : RelativePosition = { distances : [ ] , weights : [ ] } ;
762781 if ( toConvert . length === 0 ) return relatives ;
763782
783+ if ( ! isFinitePoint ( source ) || ! isFinitePoint ( target ) || equal ( source , target ) ) return relatives ;
784+
764785 const mainVector = array ( [ target . x - source . x , target . y - source . y ] ) ; // Edge vector
786+ if ( mainVector . x === 0 && mainVector . y === 0 ) return relatives ;
765787 const orthoVector = array ( [ - mainVector . y , mainVector . x ] ) // Perpendicular vector
766788 . normalize ( ) ; //Normalized to have the distance expressed in pixels https://math.stackexchange.com/a/413235/683621
767- let transform = array ( [
789+ const transform = array ( [
768790 [ mainVector . x , mainVector . y ] ,
769791 [ orthoVector . x , orthoVector . y ] ,
770792 ] ) . inv ( ) ; // Should always be invertible if the ortho vector is indeed perpendicular
771793
772794 for ( let coord of toConvert ) {
795+ if ( ! isFinitePoint ( coord ) ) continue ;
773796 const absolute = array ( [ [ coord . x - source . x , coord . y - source . y ] ] ) ;
774797 const relative = absolute . multiply ( transform ) ;
775- relatives . weights . push ( relative . get ( 0 , 0 ) )
776- relatives . distances . push ( relative . get ( 0 , 1 ) )
798+ const weight = relative . get ( 0 , 0 ) ;
799+ const distance = relative . get ( 0 , 1 ) ;
800+ if ( ! Number . isFinite ( weight ) || ! Number . isFinite ( distance ) ) continue ;
801+ relatives . weights . push ( weight )
802+ relatives . distances . push ( distance )
777803 }
778804 return relatives ;
779805 }
@@ -869,7 +895,8 @@ export class DiagramService {
869895 }
870896}
871897
872- function samePoint ( p1 : Position , p2 : Position ) {
898+ function samePoint ( p1 ?: Position | null , p2 ?: Position | null ) {
899+ if ( ! p1 || ! p2 ) return false ;
873900 return p1 . x === p2 . x && p1 . y === p2 . y
874901}
875902
0 commit comments