
proc MakeAreas { } {
    global area aindex wall p1 p2 done area_region
    catch { 
	unset area
    }
    catch { 
	unset done
    }
    set aindex 0
    foreach i [array names wall] {
	if {![info exists done($i,[wall-freg $wall($i)])]} {
	    FollowWall .edit.canvas $i [wall-freg $wall($i)]
	    lappend area_region($aindex) [wall-freg $wall($i)]
	    incr aindex
	}
    }
    foreach i [array names wall] {
	if {![info exists done($i,[wall-breg $wall($i)])]} {
	    FollowWall .edit.canvas $i [wall-breg $wall($i)]
	    lappend area_region($aindex) [wall-breg $wall($i)]
	    incr aindex
	}
    }
}

proc AreaPoint { area i } {
    return [lindex $area $i]
}

proc SortWalls { canvas } {
    global p1 p2 wall selection
    if {[info exists selection]} {
	set tags [$canvas gettags $selection]
	if {"[lindex $tags 1]"=="wall"} {
	    set wfirst [GetNumber [lindex $tags 0]]

	    set reg [lindex $wall($wfirst) 3]
	    set v [lindex $wall($wfirst) 1]
	    set w ""
	    set walls $p1($v)
	    set found ""
	    while {$wfirst!=$w} {
		unset found
		foreach i $walls {
		    if {   ([lindex $wall($i) 3]==$reg)
			|| ([lindex $wall($i) 4]==$reg)
			&& ($i!=$w) } {
			    lappend path $i
			    set found $i
			    break
			}
		}
		if {![info exists found]} {
		    return
		}
		set w $found
		set v [lindex $wall($w) 1]
		set walls $p1($v)
	    }
	    for { set i 0 } { $i<[llength $path] } { incr i } {
		set tmp($i) $wall([lindex $path $i])
	    }
	    for { set i 0 } { $i<[llength $path] } { incr i } {
		set wall([expr $wfirst+$i]) $tmp($i)
	    }
	    set fn [format "/tmp/world%d" [pid]]
	    WriteWorld $fn
	    ReadWorld $fn $canvas 
	}
    }
}

# find next wall starting/ending at point v
# with some side belonging to region r

proc FindNext { v r } {
    global p1 p2 wall done

# try v as starting point 

    set walls $p1($v)
    foreach w $walls {
	if {(  ([wall-freg $wall($w)]==$r)
	     ||([wall-breg $wall($w)]==$r))
	     &&(![info exists done($w,$r)])} {
	    return "$w start"
	}
    }

#  try v as end point

    set walls $p2($v)
    foreach w $walls {
	if {(  ([wall-freg $wall($w)]==$r)
	     ||([wall-breg $wall($w)]==$r))
	     &&(![info exists done($w,$r)]) } {
	    return "$w end"
	}
    }
    echo "no next wall found: $v $r"
}

proc FollowWall { canvas wnum rnum } {
    global area aindex wall vertex done

    if {[info exists done($wnum,$rnum)]} {
#	echo already done wnum $wnum rnum $rnum
    }
    set next $wnum
    set v [wall-end $wall($next)]
    while (1) {
	set next [FindNext $v $rnum]
	set direction [lindex $next 1]
	set next [lindex $next 0]
	set done($next,$rnum) 1
	if {"$direction"=="start"} {
	    set v [wall-end $wall($next)]
	} else {
	    set v [wall-start $wall($next)]
	}
	lappend area($aindex) $vertex($v)
	if {$next==$wnum} {
	    return
	}
    }
}

proc UpdateAreas { canvas } {
    global area queue aindex
    $canvas delete area
    catch { MakeAreas }
    if {[info exists area]} {
	for { set i 0 } { $i<$aindex } { incr i } {
		echo area($i)=$area($i)
		DrawPolygon $canvas $i 
	}
    }
    SortAreas $canvas
}

# sort all the areas in the display list in such a way, that 
# the biggest ones come first, the smaller (enclosed) come
# last. This should ensure, that no areas are completely obscured
# by others.

proc SortAreas { canvas } {
    global area aindex
    for { set i 0 } { $i<$aindex } { incr i } {
	# area which is to be lowered in respect to all enclosed areas
	set base [format a%d $i]
	# get bounding box
	set box [$canvas bbox $base]
	echo base=$base box=$box
	if {[llength $box]==4} {
	    set list [eval $canvas find enclosed $box]
	    echo list=$list
	    foreach object $list {
		set tags [$canvas gettags $object] 
		# first check if it is an area (not a vertex, no wall)
		if {"[lindex $tags 1]"=="area"} {
		    echo encloses object=[lindex $tags 0]
		    $canvas raise $object $base
		}
	    }
	}
    }
    $canvas raise wall
    $canvas raise vertex
}

proc DrawPolygon { canvas anum } {
    global area scale
    foreach c [eval concat $area($anum)] {
	lappend coords [expr $c*$scale]
    }
    catch {
	eval $canvas create polygon $coords -fill \"\" \
	    -tags \{ [format a%d $anum] area \}
    }
    $canvas lower area
}

