#
# QCad
# (c) Q Solutions 1998
#
#

#
#
# Geometry Processing Routines
#

#
# geomCLip step xy	  - clip xy to lie on largest grid point of size step
# geomShift xy dy list - translate coordinates by dy dx ammount
# geomScale sx sy list - scale each coord by sx and sy
# geomRotate ox oy list - rotate coords about ox,oy counter clockwise
# geomRotateBack ox oy list  - as rotate but clockwise
# geomMirrorX ox oy list - mirror object about line y
# geomMirrorY ox oy list - as mirror x but with line x
# geomSquare s x y 		- generate square of size s about x y
# geomBetween x x1 x2	- returns 1 if x lies between x1 x2
# geomCenter s l		- returns center of object list l cliped to s
# geomWithin box1 box2	- returns true if bbox2 is within bbox1 (enclosed)
#
#
#


proc geomClip { step args} {

	if { $step == 0 } {
		return [join $args]
	}
	foreach xy [join $args] {
		lappend clipped [expr round($xy / $step) * $step] 
	}
	return $clipped
}

proc geomShift { dx dy args} {

	set res {}
	set list [join $args]

	foreach {x y} $list {
		lappend res [expr $dx + $x] [expr $dy + $y]
	}
	return $res
}

proc geomScale { dx dy args} {

	set res {}
	set list [join $args]
	foreach {x y} $list {
		lappend res [expr $dx * $x] [expr $dy * $y]
	}
	return $res
}

proc geomRotate { Ox Oy args} {

	set res {}
	set list [join $args]
	foreach {x y} $list {
		lappend res [expr $Ox + $y - $Oy] [expr $Oy - $x + $Ox]
	}
	return $res
}

proc geomRotateBack { Ox Oy args} {

	set res {}
	set list [join $args]
	foreach {x y} $list {
		lappend res [expr $Ox + $y - $Oy] [expr $Oy + $x - $Ox]
	}
	return $res
}

proc geomMirrorX { Ox Oy args} {

	set res {}
	set list [join $args]
	foreach {x y} $list {
		set x [ expr $Ox - ($x - $Ox) ]
		lappend res $x $y
	}
	return $res
}

proc geomMirrorY { Ox Oy args} {

	set res {}
	set list [join $args]
	foreach {x y} $list {
		set y [ expr $Oy - ($y - $Oy)  ]
		lappend res $x $y
	}
	return $res
}

#
# Roate by angle
#
proc geomRotateAny { angle Ox Oy args} {

	set res {}
	set list [join $args]
	set angle [expr $angle / 180 * 3.141592654]
	foreach {x y } $list {
		set x [ expr ($x - $Ox) ]
		set y [ expr ($y - $Oy) ]
		set x1 [expr $x * cos($angle) + $y * sin($angle) + $Ox]
		set y1 [expr $x * sin($angle) - $y * cos($angle) + $Oy]
		lappend res $x1 $y1
	}
	return $res
}


proc geomSquare { s x y} {

	return [list [expr $x - $s] [expr $y - $s] [expr $x + $s] [expr $y + $s]]
}

proc geomBetween {x x1 x2} {

	if { $x1 > $x2 } {
		set tmp $x1
		set x1 $x2
		set x2 $tmp
	}
	return [expr $x >= $x1 && $x <= $x2]
}

proc geomCenter {step args} {

	set list [join $args]
	set minx 1e32
	set miny 1e32
	set maxx -1e32
	set maxy -1e32
	foreach {x y } $list {
		set minx [min $x $minx]
		set maxx [max $x $maxx]
		set maxy [max $y $maxy]
		set miny [min $y $miny]
	}
	set cx [geomClip $step [expr $minx + ($maxx - $minx) / 2.0]]
	set cy [geomClip $step [expr $miny + ($maxy - $miny) / 2.0]]

	return [list $cx $cy]

}

proc geomWithin { bbox1 bbox2 } {

	scan $bbox1 "%f %f %f %f" ox1 oy1 ox2 oy2
	scan $bbox2 "%f %f %f %f" ix1 iy1 ix2 iy2

	return [expr [geomBetween $ix1 $ox1 $ox2] && \
				 [geomBetween $iy1 $oy1 $oy2] && \
				 [geomBetween $ix2 $ox1 $ox2] && \
				 [geomBetween $iy2 $oy1 $oy2] ]
}


proc max { v1 v2 } {
	if { $v1 > $v2 } { return $v1}
	return $v2
}

proc min { v1 v2 } {
	if { $v1 < $v2 } { return $v1}
	return $v2
}















