# ----------------------------------------------------------------------------
# utilitaires pour la saisie de traces
#
# Michel Beaudouin-Lafon
# Nov, 1997
#
# mailto:mbl@lri.fr
# http://www-ihm.lri.fr/~mbl/
# ----------------------------------------------------------------------------

# MarkIsStraight line
#	Retourne 1 si la serie de points peut etre consideree comme un segment de droite
#	line est de la forme {x1 y1 x2 y2 ... xn yn}
#
#	On teste si chacun des points est suffisamment proche du segment
#	(x0, y0)-(xn, yn).  Les lignes trop courtes sont rejetees.
#
#	la tolerance est de 3 pixels
#	la longueur minimale des lignes est de 15 pixels
#
proc MarkIsStraight {line} {
	set l [llength $line]
	if {$l % 2 != 0} {
		# il faut un nombre pair de coordonnees
		return -1
	}
	
	# extremites
	set x0 [lindex $line 0]
	set y0 [lindex $line 1]
	set xn [lindex $line [expr $l -2]]
	set yn [lindex $line [expr $l -1]]
	
	# (nx ny) = vecteur normal unitaire
	set dx [expr $xn - $x0]
	set dy [expr $yn - $y0]
	set norm [expr sqrt ($dx*$dx + $dy*$dy)]
	set nx [expr $dy / $norm]
	set ny [expr - $dx / $norm]
	
	# ne pas traiter les lignes trop courtes
	if {$norm < 15} {
		return 0
	}
	
	# calculer la distance de chaque point au segment
	foreach {x y} $line {
		set d [expr ($x - $x0)*$nx + ($y - $y0)*$ny]
		if {abs($d) > 3} {
			return 0
		}
	}
	return 1
}

# MarkIsFlick line
#	Si line est un segment de droite et si sa direction est reconnue
#	(N, S, E, W, NE, NW, SE, SW) retourner la direction, sinon retourner "line"
#	si c'est une droite ou "mark" sinon
#
#	la tolerance sur le cosinus de l'angle entre la direction ideale et
#	la direction effective est de 0.98, soit environ +/- 10 degres
#
proc MarkIsFlick {line} {
	# verifier que c'est une droite
	if {! [MarkIsStraight $line]} {
		return "mark"
	}
	
	# recupere les extremites et calculer la longueur
	### dommage que MarkIsStraight ait deja fait ca...
	set l [llength $line]
	set x0 [lindex $line 0]
	set y0 [lindex $line 1]
	set xn [lindex $line [expr $l -2]]
	set yn [lindex $line [expr $l -1]]
	set dx [expr $xn - $x0]
	set dy [expr $yn - $y0]
	set norm [expr sqrt ($dx*$dx + $dy*$dy)]
	set vx [expr $dx / $norm]
	set vy [expr $dy / $norm]
	
	# chercher la direction la plus proche
	set s2 [expr sqrt(2.0)/2.0]
	set s2n [expr -$s2]
	foreach {ux uy} {
		1.0 0.0
		$s2 $s2n
		0.0 -1.0
		$s2n $s2n
		-1.0 0.0
		$s2n $s2
		0.0 1.0
		$s2 $s2
	} dir {E NE N NW W SW S SE} {
		# (ux uy) est la direction et dir son nom.
		# On calcule le produit scalaire de u=(ux, uy) et v=(vx, vy)
		# Comme u.v = ||u||.||v|| cos(a), avec a angle entre u et v, et que
		# u et v sont unitaires, on peut calculer cos(a) et choisir la 
		# direction s'il est suffisamment proche de 1.
		set cosa [expr $ux*$vx + $uy*$vy]
		if {$cosa > 0.98} {
			return $dir
		}
	}
	
	return "line"
}

