1

我是 Tcl 数组的新手。我的问题如下。

我有一个带有两行 R1 和 R2 的矩形框。这些行中的每一行都有 8 个不同的值。我想在文本文件中或作为 proc 的列表输出返回这 16 个值(x 和 y 坐标)。我阅读了一些关于 Tcl proc 除非我们使用 dict 否则无法输出数组的早期帖子。所以,我会试着画一张图,这样你就可以更好地理解我的问题。

R1 x1y1 x2y2 ... x8,y8
R2 x9,y9 ... x16,y16

例如,当我在命令提示符下或在具有虚拟值的文件中运行 proc 时的预期输出

$> (1,2) (2,3) (3,4) .... (7,8)
      (9,10) (10,11) ......... (15,16)

所以这就是我尝试过的,我得到了我需要的结果。但这是硬编码的两行。我想让它能够检测有多少行,然后相应地输出行数。

proc getPointList {rect_boundary rowOffset colOffset rowIncr colIncr } {
 set cordlist $rect_boundary

 set xl  [lindex $cordlist 0]
 set yl  [lindex $cordlist 1]
 set xh  [lindex $cordlist 2]      
 set yh  [lindex $cordlist 3]

 set list "" ;

 for {set y [expr {$yh - $colOffset}]} {$y >= [expr {$yl + $colOffset}]} { incr y $colIncr } {

    for {set x [expr {$xl + $rowOffset}]} {$x <= [expr {$xh - $rowOffset}]} { incr x $rowIncr } {

            set list "$list $x $y" ;
            puts "Value of x is: $x"; puts "\t Value of y is: $y" ;  
        } 
 }
return $list  
}

set rect_boundary {10 15 100 40}     # xl yl xh yh
set rowOffset 5
set colOffset 5
set rowIncr 10
set colIncr 15

我需要在此代码中基于 yh-yl 和 xh-xl 实现一些逻辑,以计算矩形的高度和宽度并相应地输出行

调用proc的命令

$> getPointList $rect_boundary $rowOffset $colOffset $rowIncr $colIncr

只是为了您的理解,在特定行的矩形内有八个 x,y 点。x 偏移量是从左边界或右边界开始的一行上的第一个 x 点,此后所有点都由我称为 rowIncr 的增量值分隔。列也是如此。

预期输出:这是上面的代码所做的,但它被硬编码为两行。如果行和列是可变的,我想增加和实现逻辑。

$>  R1:  (15 40) (25 40) (35 40) (45 40) (55 40) (65 40) (75 40) (85 40) (95 40)
    R2:  (15 15) (25 15) (35 15) (45 15) (55 15) (65 15) (75 15) (85 15) (95 15)

矩形图像以获得更好的清晰度,因为这件事不会让我更新图片

__________________________________________________________________________ (100,40)
|                       |- 5                                              |
|   .          .        .       .        .       .        .        .      |
|                               |- 15                                     |
|-5-.          . --10---.       .        .       .        .        .      |
|                                                                         |
|_________________________________________________________________________|
(10,15)    

对于杰瑞:

Case1  rowIncr 10 colIncr 20
__________________________________________________________________________ (80,40)
|                       |- 5                                              |
|   .          .        .       .        .       .        .        .      |
|                               |- 20                                     |
|-5-.          . --10---.       .        .       .        .        .      |
|                                                                         |
|_________________________________________________________________________|
(10,10)

Case2   rowIncr 20 colIncr 35
_________________________________________________ (100,70)
|                       |- 5                     |
|   .          .        .       .        .       |
|                               |- 35            |
|-5-.          . --20---.       .        .       |
|              |                         |-5     |
|________________________________________________|
(10,25)

等等 ...

4

3 回答 3

1

好的,我想我现在明白了你想要做什么,而且我认为你的 proc 在一些修复之后可以用于任意数量的行:

set output [open "output.txt" w]

proc getPointList {rect_boundary rowOffset colOffset plist} {
    global output

    set cordlist $rect_boundary
    set xl  [lindex $cordlist 0]
    set yl  [lindex $cordlist 1]
    set xh  [lindex $cordlist 2]      
    set yh  [lindex $cordlist 3]

    set xpoints [llength [lindex $plist 0]]
    set ypoints [llength $plist]
    set rowIncr [expr {($xh-$xl-2*$rowOffset)/($xpoints-1)}]
    set colIncr [expr {($yh-$yl-2*$colOffset)/($ypoints-1)}]

    set count 0
    set list ""

    for {set y [expr {$yh - $colOffset}]} {$y >= [expr {$yl + $colOffset}]} {incr y -$colIncr} {

        for {set x [expr {$xl + $rowOffset}]} {$x <= [expr {$xh - $rowOffset}]} {incr x $rowIncr} {
            lappend list "($x,$y)"
        }
        incr count
        puts $output "R$count: [join $list " "]"
        set list ""
    }
}

set plist {{A B C D E} {A B C D E} {A B C D E} {A B C D E} {A B C D E}}
set rect_boundary {0 0 100 100}
set rowOffset 0
set colOffset 0

getPointList $rect_boundary $rowOffset $colOffset $plist

close $output

我改变了colIncr放置更多行。

在第一个循环中,我使用了因为如果你从更高的坐标incr y -$colIncr开始,这实际上是一个递减。y

我还更改了输出结构以匹配您要查找的结构。上面的代码片段返回坐标:

R1: (0,100) (25,100) (50,100) (75,100) (100,100) 
R2: (0,75) (25,75) (50,75) (75,75) (100,75) 
R3: (0,50) (25,50) (50,50) (75,50) (100,50) 
R4: (0,25) (25,25) (50,25) (75,25) (100,25) 
R5: (0,0) (25,0) (50,0) (75,0) (100,0)

编辑:添加了可变偏移量、空白最后一行和每行可变列。

proc getPointList {rect_boundary uRowOffset lRowOffset uColOffset lColOffset plist} {
    set cordlist $rect_boundary
    set xl  [lindex $cordlist 0]
    set yl  [lindex $cordlist 1]
    set xh  [lindex $cordlist 2]      
    set yh  [lindex $cordlist 3]

    set xpoints 0
    foreach r $plist {
        if {[llength $r] > $xpoints} {set xpoints [llength $r]}
    }

    set ypoints [llength $plist]
    set rowIncr [expr {($xh-$xl-$lRowOffset-$uRowOffset)/($xpoints-1)}]
    set colIncr [expr {($yh-$yl-$lColOffset-$uColOffset)/$ypoints}]

    set count 0
    set list ""

    for {set y [expr {$yh - $uColOffset}]} {$y >= [expr {$yl + $lColOffset}]} {incr y -$colIncr} {
        set x [expr {$xl + $lRowOffset}]
        foreach n [lindex $plist $count] {
            lappend list $x $y
            incr x $rowIncr
        }
        incr count
        if {$count == $ypoints} {return $list}
    }
}

set plist {{A B C D X} {E F G H} {I K L} {M N}}
set qlist 1
foreach n $plist {
    set pattern$plist $n
    incr qlist
}

set rect_boundary {0 0 100 100}
set upperRowOffset 0
set lowerRowOffset 0
set upperColOffset 0
set lowerColOffset 0

set pointList [getPointList $rect_boundary $upperRowOffset $lowerRowOffset $upperColOffset $lowerColOffset $plist]

set count 1
foreach sub_list $plist {
    foreach n $sub_list {
        set pattern$count $n
        incr count
    }
}

set count 1
foreach {a b} $pointList {
    set text "pattern$count"
    puts "command -point $a,$b -text [set $text]"
    incr count 
}
于 2013-08-22T10:06:51.380 回答
0

好吧,使用 Tcl 8.6

proc parsedata {input} {
    lmap a [split $input \n] {
        lmap b [split $b \t] {
           regexp {x(\d+),?\s*y(\d+)} $b -> c d
           list $c $d
        }
    }
}

现在您可以处理数据,例如:

foreach line [parsedata $input] {
    puts [lmap pair $line {
        expr {"([lindex $line 0],[linedex $line 1])"}
    }
}
于 2013-08-20T08:46:52.170 回答
0

如何组织嵌套列表取决于您。以最简单的形式,返回一个列表:

set result {x1 y1 x2 y2 ... x16 y16}

或者,您可以有一个包含两行的列表:

set result {
    {x1 y1 x2 y2 ... x8 y8}
    {x9 y9 x10 y10 ... x16 y16}
}

或者,更复杂:每一对都是一个子列表:

set result {
    { {x1 y1} {x2 y2} ... }
    { {x9 y9} {x10 y10} ... }
}

在这种情况下,我认为您不想使用数组。仅供参考,TCL 中的“数组”相当于其他语言中的哈希

于 2013-08-19T21:30:10.073 回答