@@ -13,12 +13,13 @@ export const generateJumperX4Grid = ({
1313 innerColChannelPointCount = 1 ,
1414 innerRowChannelPointCount = 1 ,
1515 regionsBetweenPads = false ,
16- outerPaddingX = 0.5 ,
17- outerPaddingY = 0.5 ,
16+ outerPaddingX : outerPaddingXParam = 0.5 ,
17+ outerPaddingY : outerPaddingYParam = 0.5 ,
1818 outerChannelXPointCount,
1919 outerChannelYPointCount,
2020 orientation = "vertical" ,
2121 center,
22+ bounds,
2223} : {
2324 cols : number
2425 rows : number
@@ -33,12 +34,8 @@ export const generateJumperX4Grid = ({
3334 outerChannelYPointCount ?: number
3435 orientation ?: "vertical" | "horizontal"
3536 center ?: { x : number ; y : number }
37+ bounds ?: { minX : number ; maxX : number ; minY : number ; maxY : number }
3638} ) : JumperGraph => {
37- // Calculate outer channel points: use provided value or derive from outer padding
38- const effectiveOuterChannelXPoints =
39- outerChannelXPointCount ?? Math . max ( 1 , Math . floor ( outerPaddingX / 0.4 ) )
40- const effectiveOuterChannelYPoints =
41- outerChannelYPointCount ?? Math . max ( 1 , Math . floor ( outerPaddingY / 0.4 ) )
4239 const regions : JRegion [ ] = [ ]
4340 const ports : JPort [ ] = [ ]
4441
@@ -65,6 +62,25 @@ export const generateJumperX4Grid = ({
6562 const cellHeight = row1CenterY - row4CenterY + padHeight // total height of pads region
6663 const verticalSpacing = cellHeight + marginY
6764
65+ // Calculate outer padding from bounds if specified
66+ let outerPaddingX = outerPaddingXParam
67+ let outerPaddingY = outerPaddingYParam
68+ if ( bounds ) {
69+ // Content dimensions (without outer padding)
70+ const contentWidth = cols * cellWidth + ( cols - 1 ) * marginX
71+ const contentHeight = rows * cellHeight + ( rows - 1 ) * marginY
72+ const boundsWidth = bounds . maxX - bounds . minX
73+ const boundsHeight = bounds . maxY - bounds . minY
74+ outerPaddingX = ( boundsWidth - contentWidth ) / 2
75+ outerPaddingY = ( boundsHeight - contentHeight ) / 2
76+ }
77+
78+ // Calculate outer channel points: use provided value or derive from outer padding
79+ const effectiveOuterChannelXPoints =
80+ outerChannelXPointCount ?? Math . max ( 1 , Math . floor ( outerPaddingX / 0.4 ) )
81+ const effectiveOuterChannelYPoints =
82+ outerChannelYPointCount ?? Math . max ( 1 , Math . floor ( outerPaddingY / 0.4 ) )
83+
6884 // Store cells for later port connections
6985 const cells : {
7086 pad1 : JRegion
@@ -566,7 +582,9 @@ export const generateJumperX4Grid = ({
566582 `${ idPrefix } :T-R` ,
567583 top ,
568584 right ,
569- isLastCol ? effectiveOuterChannelXPoints : innerColChannelPointCount ,
585+ isLastCol
586+ ? effectiveOuterChannelXPoints
587+ : innerColChannelPointCount ,
570588 ) ,
571589 )
572590 // Top connects to pad1, pad8, and underjumper
@@ -613,7 +631,9 @@ export const generateJumperX4Grid = ({
613631 `${ idPrefix } :B-R` ,
614632 bottom ,
615633 right ,
616- isLastCol ? effectiveOuterChannelXPoints : innerColChannelPointCount ,
634+ isLastCol
635+ ? effectiveOuterChannelXPoints
636+ : innerColChannelPointCount ,
617637 ) ,
618638 )
619639 // Bottom connects to pad4, pad5, and underjumper
@@ -817,24 +837,28 @@ export const generateJumperX4Grid = ({
817837 )
818838 }
819839 // T-T connection between horizontally adjacent cells (first row only)
840+ // This is a vertical boundary, so use Y point count for outer edge
820841 if ( top && prevCell . top ) {
821842 ports . push (
822843 ...createMultiplePorts (
823844 `cell_${ row } _${ col - 1 } ->cell_${ row } _${ col } :T-T` ,
824845 prevCell . top ,
825846 top ,
826- innerRowChannelPointCount ,
847+ effectiveOuterChannelYPoints ,
827848 ) ,
828849 )
829850 }
830851 // B-B connection between horizontally adjacent cells
852+ // This is a vertical boundary; use Y points for outer edge (last row), inner points otherwise
831853 if ( bottom && prevCell . bottom ) {
832854 ports . push (
833855 ...createMultiplePorts (
834856 `cell_${ row } _${ col - 1 } ->cell_${ row } _${ col } :B-B` ,
835857 prevCell . bottom ,
836858 bottom ,
837- innerRowChannelPointCount ,
859+ isLastRow
860+ ? effectiveOuterChannelYPoints
861+ : innerRowChannelPointCount ,
838862 ) ,
839863 )
840864 }
@@ -901,7 +925,9 @@ export const generateJumperX4Grid = ({
901925 `cell_${ row - 1 } _${ col } ->cell_${ row } _${ col } :B-R` ,
902926 aboveCell . bottom ! ,
903927 right ,
904- isLastCol ? effectiveOuterChannelXPoints : innerColChannelPointCount ,
928+ isLastCol
929+ ? effectiveOuterChannelXPoints
930+ : innerColChannelPointCount ,
905931 ) ,
906932 )
907933 }
@@ -910,11 +936,12 @@ export const generateJumperX4Grid = ({
910936
911937 let graph : JumperGraph = { regions, ports }
912938
913- // Apply transformations based on orientation and center
939+ // Apply transformations based on orientation, center, and bounds
914940 const needsRotation = orientation === "horizontal"
915941 const needsCentering = center !== undefined
942+ const needsBoundsTransform = bounds !== undefined
916943
917- if ( needsRotation || needsCentering ) {
944+ if ( needsRotation || needsCentering || needsBoundsTransform ) {
918945 // Calculate current graph bounds and center
919946 const currentBounds = calculateGraphBounds ( graph . regions )
920947 const currentCenter = computeBoundsCenter ( currentBounds )
@@ -930,8 +957,16 @@ export const generateJumperX4Grid = ({
930957 matrices . push ( rotate ( - Math . PI / 2 ) )
931958 }
932959
933- // Translate to target center (or back to current center if no center specified)
934- const targetCenter = center ?? currentCenter
960+ // Translate to target center
961+ // Priority: explicit center > bounds center > current center
962+ let targetCenter : { x : number ; y : number }
963+ if ( center ) {
964+ targetCenter = center
965+ } else if ( bounds ) {
966+ targetCenter = computeBoundsCenter ( bounds )
967+ } else {
968+ targetCenter = currentCenter
969+ }
935970 matrices . push ( translate ( targetCenter . x , targetCenter . y ) )
936971
937972 const matrix = compose ( ...matrices )
0 commit comments