3

頂点のコレクションがあります: [ x1 y1 x2 y2 .. xn yn ]

それらの座標の中心を変更したいと思います。だから私は試します:

proc changeCenter { vertices X Y } {
    set myList [list]
    foreach element $vertices {
        lappend myList [expr [lindex $element 0] + $X]
        lappend myList [expr [lindex $element 1] + $Y]
    }

 return $myList 
}

しかし、そのパフォーマンスは遅すぎます。

上記のコードをより効果的に変更するにはどうすればよいですか、または頂点の表現を変更する必要があるのでしょうか?

4

2 に答える 2

5

これを行う最も簡単な方法は、式をブレースすることです。

proc changeCenter { vertices X Y } {
    set myList [list]
    foreach {x0 y0} $vertices {
        lappend myList [expr {$x0 + $X}]
        lappend myList [expr {$y0 + $Y}]
    }

    return $myList 
}

これにはいくつかの利点があります。

  • 数値を文字列に変換して戻す必要はありません。
  • 式はコンパイルできます。
  • 文字列表現によって引き起こされる厄介な丸め誤差は発生しません。
  • 実行したくないコードの挿入を防ぎます。

詳細については、この wiki エントリを参照してください。

ネストされたリストを入力として使用しない場合は、複数の変数で foreach を使用します。

于 2013-06-24T17:26:41.673 に答える
5

changeCenter プロシージャは、頂点コレクションがペアのリスト ( {{x1 y1} {x2 y2} ...}) であることを示していますが、フラット リストを返しています。

proc changeCenter { vertices deltaX deltaY } {
    set recentered [list]
    foreach vertex $vertices {
        lassign $vertex x y
        lappend recentered [list [expr {$x + $deltaX}] [expr {$y + $deltaY}]]
    }
    return $recentered 
}

頂点が実際にフラット リスト ( {x1 y1 x2 y2 ...}) である場合は、一度に 2 つの要素のリストを読み取ります。

proc changeCenter { vertices deltaX deltaY } {
    set recentered [list]
    foreach {x y} $vertices {
        lappend recentered [expr {$x + $deltaX}] [expr {$y + $deltaY}]
    }
    return $recentered 
}

ベンチマークはしていませんが、頂点リストをその場で更新する方が、新しいリストに追加するよりも高速であると思われます。

proc changeCenter { vertices deltaX deltaY } {
    for {set i 0} {$i < [llength $vertices]} {incr i} {
        lset vertices $i 0 [expr {[lindex $vertices $i 0] + $deltaX}] 
        lset vertices $i 1 [expr {[lindex $vertices $i 1] + $deltaY}] 
    }
    return $vertices 
}

また

proc changeCenter { vertices deltaX deltaY } {
    for {set i 0} {$i < [llength $vertices]} {incr i 2} {
        lset vertices $i [expr {[lindex $vertices $i] + $deltaX}] 
        set j [expr {$i + 1}]
        lset vertices $j [expr {[lindex $vertices $j] + $deltaY}] 
    }
    return $vertices
}

上記の頂点リストの構造に依存します。


頂点リストを名前で渡すと、さらに高速になります (データのコピーは避けてください)。

proc changeCenter { verticesName deltaX deltaY } {
    upvar 1 $verticesName v
    for {set i 0} {$i < [llength $v]} {incr i 2} {
        lset v $i [expr {[lindex $v $i] + $deltaX}] 
        set j [expr {$i + 1}]
        lset v $j [expr {[lindex $v $j] + $deltaY}] 
    }
    # no need to return a value
}

変数で呼び出します:

changeCenter vertices 1 2
于 2013-06-24T18:08:05.550 に答える