@@ -1841,56 +1841,77 @@ execute actions in ${targetPackageName}
18411841 const calculateMergePoint = useCallback ( ( avgSource : { x : number ; y : number } , targetNode : Node ) => {
18421842 const targetCenterX = targetNode . position . x + NODE_DIMENSIONS . width / 2 ;
18431843 const targetCenterY = targetNode . position . y + NODE_DIMENSIONS . height / 2 ;
1844+
1845+ // Place merge point vertically under/above the target center so
1846+ // the last segment into the class box is a straight line into
1847+ // the middle (no diagonal hit on the left/right side).
18441848 return {
1845- x : avgSource . x + ( targetCenterX - avgSource . x ) * 0.4 ,
1846- y : avgSource . y + ( targetCenterY - avgSource . y ) * 0.4
1849+ x : targetCenterX ,
1850+ y : avgSource . y + ( targetCenterY - avgSource . y ) * 0.4 ,
18471851 } ;
18481852 } , [ ] ) ;
18491853
1850- // Calculate merge points for UML edges with same target
1854+ // Calculate merge points for UML inheritance edges with same target.
1855+ // We keep merge visualization ONLY for inheritance (like multiple
1856+ // subclasses pointing to the same superclass), not for other UML
1857+ // relationships. This gives a clean "fan-in" into the superclass
1858+ // while keeping compositions and associations as simple lines.
18511859 const umlMergeData = useMemo ( ( ) => {
18521860 const mergePointsMap = new Map < string , { x : number ; y : number ; mergeGroupId : string } > ( ) ;
18531861 const firstInGroupMap = new Map < string , string > ( ) ;
18541862 const mergeGroupSourceNodesMap = new Map < string , string [ ] > ( ) ;
18551863
1856- // Count UML edges per source node
1864+ // Consider only UML inheritance edges for merging
1865+ const umlInheritanceEdges = uniqueEdges . filter (
1866+ ( e ) => e . type === 'uml' && ( e . data as any ) ?. relationshipType === 'inheritance'
1867+ ) ;
1868+
1869+ if ( umlInheritanceEdges . length === 0 ) {
1870+ return { mergePointsMap, firstInGroupMap, mergeGroupSourceNodesMap } ;
1871+ }
1872+
1873+ // Count inheritance edges per source node
18571874 const edgesPerSource = new Map < string , number > ( ) ;
1858- uniqueEdges . filter ( e => e . type === 'uml' ) . forEach ( edge => {
1875+ umlInheritanceEdges . forEach ( ( edge ) => {
18591876 edgesPerSource . set ( edge . source , ( edgesPerSource . get ( edge . source ) || 0 ) + 1 ) ;
18601877 } ) ;
18611878
1862- // Group UML edges by target
1879+ // Group inheritance edges by target (superclass)
18631880 const edgesByTarget = new Map < string , Edge [ ] > ( ) ;
1864- uniqueEdges . filter ( e => e . type === 'uml' ) . forEach ( edge => {
1881+ umlInheritanceEdges . forEach ( ( edge ) => {
18651882 const existing = edgesByTarget . get ( edge . target ) || [ ] ;
18661883 existing . push ( edge ) ;
18671884 edgesByTarget . set ( edge . target , existing ) ;
18681885 } ) ;
18691886
1870- // Process each target group
1887+ // For each superclass, create one merge point for eligible subclasses
18711888 edgesByTarget . forEach ( ( edgesGroup , targetId ) => {
18721889 if ( edgesGroup . length < 2 ) return ;
18731890
1874- const eligibleEdges = edgesGroup . filter ( edge => ( edgesPerSource . get ( edge . source ) || 0 ) === 1 ) ;
1891+ // Only merge subclasses that connect to this superclass once
1892+ const eligibleEdges = edgesGroup . filter (
1893+ ( edge ) => ( edgesPerSource . get ( edge . source ) || 0 ) === 1
1894+ ) ;
18751895 if ( eligibleEdges . length < 2 ) return ;
18761896
18771897 eligibleEdges . sort ( ( a , b ) => a . source . localeCompare ( b . source ) ) ;
18781898
1879- const targetNode = nodes . find ( n => n . id === targetId ) ;
1899+ const targetNode = nodes . find ( ( n ) => n . id === targetId ) ;
18801900 if ( ! targetNode ) return ;
18811901
18821902 const avgSourcePos = calculateAverageSourcePosition ( eligibleEdges ) ;
18831903 const mergePoint = calculateMergePoint ( avgSourcePos , targetNode ) ;
18841904 const mergeGroupId = `merge-${ targetId } ` ;
18851905
1886- mergeGroupSourceNodesMap . set ( mergeGroupId , eligibleEdges . map ( e => e . source ) ) ;
1887- eligibleEdges . forEach ( ( edge , index ) => {
1906+ mergeGroupSourceNodesMap . set (
1907+ mergeGroupId ,
1908+ eligibleEdges . map ( ( e ) => e . source )
1909+ ) ;
1910+ eligibleEdges . forEach ( ( edge ) => {
18881911 mergePointsMap . set ( edge . id , { ...mergePoint , mergeGroupId } ) ;
1889- console . log ( ` Edge ${ index } : ${ edge . id . slice ( - 8 ) } (source: ${ edge . source . slice ( - 6 ) } )` ) ;
18901912 } ) ;
18911913
18921914 firstInGroupMap . set ( mergeGroupId , eligibleEdges [ 0 ] . id ) ;
1893- console . log ( `✨ Merge group ${ mergeGroupId } : First edge = ${ eligibleEdges [ 0 ] . id . slice ( - 8 ) } ` ) ;
18941915 } ) ;
18951916
18961917 return { mergePointsMap, firstInGroupMap, mergeGroupSourceNodesMap } ;
0 commit comments