Home

My Tips

私が頻繁に再作成するコード

Tcl

c#のプロパティのset/getのような実装

	proc Config { name args } {
		global _config_
		switch [llength $args] {
			0 {
				return $_config_($name)
			}
			1 {
				set _config_($name) [lindex $args 0]
				return $_config_($name)
			}
		}
	}
	Config version 1 ;# これで設定
	puts "version [Config version]" ;# これで取得

	itcl::class A {
	    variable a
		public method A { args } {
			switch [llength $args] {
				0 {
					return $a
				}
				1 {
					set a [lindex $args 0]
					return $a
				}
			}
		}
	}
	

関数名でプロパティの空間を分けるような実装

下の例では、_config_, _gvar_という大域変数が用いられる。
	proc storage { vname name args } {
		upvar #0 $vname x
		if {[llength $args] > 0} {
			set x($name) [lindex $args 0]
		}
		return $x($name)
	}

	proc config { name args } { return [eval [subst "storage _config_ $name $args"]] }
	proc gvar { name args } { return [eval [subst "storage _gvar_ $name $args"]] }

	# 使い方
	config version 1.0
	gvar state idle
	if ![string compare idle [gvar state]] {
	    ...
	}
	

操作を指定してプロパティを実装

	proc Config { cmd name args } {
		global _config_
		switch $cmd {
			Set {
				if {[llength $args] > 0} {
					set _config_($name) [lindex $args 0]
				}
				return $_config_($name)
			}
			Get {
				return $_config_($name)
			}
			Exists {
				return [info exists _config_($name)]
			}
		}
	}
	

Tk

ボックスを線でつなぐ


	    # scx scy - center position of source box.
	    # dcy dcy - center position of destination box.
	    # sw  sh  - width/height of source box.
	    # dw  dh  - width/height of destination box

		set dx [expr $dcx - $scx]
		set dy [expr $dcy - $scy]
		set slope [expr (($dy+0.0)/($dx+0.0))]
		set spoints [InterceptPoints $scx $scy $sw $sh $slope]
		set dpoints [InterceptPoints $dcx $dcy $dw $dh $slope]
		# find shortest 2 points which can construct a line.
		set min -1
		for {set i 0} {$i < [llength $spoints]} {incr i} {
			set sxy [lindex $spoints $i]
			for {set j 0} {$j < [llength $dpoints]} {incr j} {
				set dxy [lindex $dpoints $j]
				set d [Distance $sxy $dxy]
				if {$min == -1 || $d < $min} {
					set min $d
					set x1 [lindex $sxy 0]
					set y1 [lindex $sxy 1]
					set x2 [lindex $dxy 0]
					set y2 [lindex $dxy 1]
				}
			}
		}
		# draw line from (x1,y1) to (x2, y2).

	public method InterceptPoints { cx cy w h slope } {
		set x1 [expr -$w/2]
		set y1 [expr -$h/2]
		set x2 [expr $x1+$w]
		set y2 [expr $y1+$h]
		#        L1            Y = aX
		#    +--------+        X = (1/a)Y
		# L4 |        | L2
		#    +--------+
		#        L3
		
		# L1
		set ty(1) $y1
		set tx(1) [expr (1./$slope)*$ty(1)]
		# L2
		set tx(2) $x2
		set ty(2) [expr $slope*$tx(2)]
		# L3
		set ty(3) $y2
		set tx(3) [expr (1./$slope)*$ty(3)]
		# L4
		set tx(4) $x1
		set ty(4) [expr $slope*$tx(4)]

		set points {}
		for {set i 1} {$i <= 4} {incr i} {
			if {$tx($i) > [expr $x1-1] && $tx($i) < [expr $x2+1] && $ty($i) > [expr $y1-1] && $ty($i) < [expr $y2+1]} {
				lappend points [list [expr $cx+$tx($i)] [expr $cy+$ty($i)]]
			}
		}
		return $points
	}
		
	public method Distance { xy1 xy2 } {
		if {$xy1 == {} || $xy2 == {}} {
			return
		}
		set x1 [lindex $xy1 0]
		set y1 [lindex $xy1 1]
		set x2 [lindex $xy2 0]
		set y2 [lindex $xy2 1]
		set dx [expr $x2-$x1]
		set dy [expr $y2-$y1]
		return [expr sqrt(($dx*$dx) + ($dy*$dy))]
	}