HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Calculating positions along the edges of a rectangle

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
positionstheedgesrectanglecalculatingalong

Problem

I had the following three Tcl procedures, which calculate positions along three edges of a rectangle:

#---- Numbered pins at the top ---------------------------------------
# Given a list of triplets (number, name, index), place the pins for the
# signals "name" along the top edge, positioned vertically at 'y'
# and horizontally at 'number' times a constant space left of 'xRight'
# (plus an arbitrary offset of 2).
proc setNumberedTopPins {xRight y pins} {
    set padWidth 95
    foreach {number name index} $pins {
        set xOffset [expr $number * $padWidth + 2]
        setPin $name [expr $xRight-$xOffset] $y Top $index
    }
}
#---- Numbered pins at the right -------------------------------------
# The same for the right edge.
proc setNumberedRightPins {x yTop pins} {
    set padWidth 95
    foreach {number name index} $pins {
        set yOffset [expr max(0, $number * $padWidth - 2.5)]
        setPin $name $x [expr $yTop-$yOffset] Right $index
    }
}
#---- Numbered pins at the bottom ------------------------------------
# The same for the bottom edge.
proc setNumberedBottomPins {xRight y pins} {
    set padWidth 95
    foreach {number name index} $pins {
        set xOffset [expr $number * $padWidth + 2]
        setPin $name [expr $xRight-$xOffset] $y Bottom $index
    }
}


Since the code for each of the procedures is almost identical, I decided to write a single generalized procedure and three specializations of it.

I had some difficulties with generalizing the fact that the offset is sometimes applied to the second (x) and sometimes to the third (y) argument of setPin. I wanted to make sure that this decision is only taken once, outside the foreach loop.

Here is the solution I came up with:

```
#---- Numbered pins at the top ---------------------------------------
proc setNumberedTopPins {xRight y pins} {
setNumberedPins Top 2 $xRight $y $pins
}
#---- Numbered pins at the right -------------------------------------
proc setNumberedRi

Solution

I would suggest that since only 2 of the procs are close enough to identical, just "combine" those:

set padWidth 95

proc setNumberedRightPins {x yTop pins} {
    foreach {number name index} $pins {
        set yOffset [expr {max(0, $number * $::padWidth - 2.5)}]
        setPin $name $x [expr {$yTop-$yOffset}] Right $index
    }
}

proc setNumberedTopPins {args} {
    setNumberedTopOrBottomPins {*}$args Top
}

proc setNumberedBottomPins {args} {
    setNumberedTopOrBottomPins {*}$args Bottom
}

proc setNumberedTopOrBottomPins {xRight y pins side} {
    foreach {number name index} $pins {
        set xOffset [expr {$number * $::padWidth + 2}]
        setPin $name [expr {$xRight-$xOffset}] $y $side $index
    }
}


Notes:

  • always brace your expressions, gain a big performance boost



  • constants can live in the global namespace, and you access them with a fully qualified variable name

Code Snippets

set padWidth 95

proc setNumberedRightPins {x yTop pins} {
    foreach {number name index} $pins {
        set yOffset [expr {max(0, $number * $::padWidth - 2.5)}]
        setPin $name $x [expr {$yTop-$yOffset}] Right $index
    }
}

proc setNumberedTopPins {args} {
    setNumberedTopOrBottomPins {*}$args Top
}

proc setNumberedBottomPins {args} {
    setNumberedTopOrBottomPins {*}$args Bottom
}

proc setNumberedTopOrBottomPins {xRight y pins side} {
    foreach {number name index} $pins {
        set xOffset [expr {$number * $::padWidth + 2}]
        setPin $name [expr {$xRight-$xOffset}] $y $side $index
    }
}

Context

StackExchange Code Review Q#87774, answer score: 3

Revisions (0)

No revisions yet.