如何在TCL中对坐标求和

How to sum coordinates in TCL

我有一个包含 x、y、z 坐标的数据文件 (*.dat)。如下:

{26.3612117767334 40.19668960571289 54.13957977294922}
{27.351043701171875 40.57518768310547 54.05387496948242}
{29.48208999633789 42.08218765258789 56.42238235473633}

对于这个文件,我需要进行如下数学运算:

Xi + (Xf-Xi/4) ; Yi + (Yf-Yi/4) ; Zi + (Zf-Zi/4)

其中“i”是初始位置,“f”是最终位置,表示 Xi、Yi、Zi 是第一行的数据,Xf、Yf、Zf 是第二行的数据。

我需要对循环中的所有行进行这些计算,然后存储在一个单独的文件中,但我不知道如何在 TCL 中进行。预先感谢您的帮助。

因为你的文件的内容可以被视为一堆 tcl 列表,每行一个(所以基本上是一个列表的列表),解析它非常简单。

类似于:

set f [open file.dat]
set coords [read -nonewline $f]
close $f

for {set i 0} {$i < [llength $coords] - 1} {incr i} {
    lassign [lindex $coords $i] xi yi zi
    lassign [lindex $coords $i+1] xf yf zf
    set xn [expr {$xi + ($xf - $xi/4.0)}]
    set yn [expr {$yi + ($yf - $yi/4.0)}]
    set zn [expr {$zi + ($zf - $zi/4.0)}]
    puts "{$xn $yn $zn}"
}

这会跳过将最后一行作为初始坐标集的处理,因为没有下一组坐标。

我提出了另一种方法,它使用 lrange 来选择参与的子列表的重叠范围(这样我们就可以处理它们 element-wise),然后 lmap 应用相同的方法变换表达式到各个坐标轴。

# Same read-in code as Shawn's answer; it's the easiest way
set f [open file.dat]
set coords [read -nonewline $f]
close $f

foreach Ci [lrange $coords 0 end-1] Cf [lrange $coords 1 end] {
    # I often like to put expressions on their own line for clarity
    puts [list [lmap _i $Ci _f $Cf {expr {
        $_i + ($_f - $_i/4.0)
    }}]]
}

(其中的包装 list 调用将 lmap 的结果括起来。)

这是编写数学函数的好机会:

proc tcl::mathfunc::f {ai af} {
    expr {$ai * 0.75 + $af}
}

proc transform {file} {
    set fh [open $file]

    # read the first line, aka the initial "previous line"
    gets $fh line
    scan $line {{%f %f %f}} xi yi zi

    # process the rest of the file
    while {[gets $fh line] != -1} {
        scan $line {{%f %f %f}} xf yf zf
        puts "{[expr {f($xi, $xf)}] [expr {f($yi, $yf)}] [expr {f($zi, $zf)}]}"
        lassign [list $xf $yf $zf] xi yi zi
    }

    close $fh
}

transform file.dat

产出

{47.121952533721924 70.72270488739014 94.65855979919434]}
{49.9953727722168 72.51357841491699 96.96278858184814]}