Hello,
missing the possibility to measure areas in the grass tcltk map display I 
created a patch which adds such a function.
Could somebody test this patch and perhaps even merge it into the grass 
repository?
Thank you very much,
Jonas
-- 
Neu: GMX FreeDSL Komplettanschluss mit DSL 6.000 Flatrate + Telefonanschluss 
für nur 17,95 Euro/mtl.!* 
http://dslspecial.gmx.de/freedsl-surfflat/?ac=OM.AD.PD003K11308T4569a
--- grass/grass/branches/releasebranch_6_4/gui/tcltk/gis.m/mapcanvas.tcl	2009-04-18 16:08:16.000000000 +0200
+++ mapcanvas.tcl-with-marea	2009-04-18 16:51:23.000000000 +0200
@@ -65,7 +65,12 @@
 	variable liney1 
 	variable linex2 
 	variable liney2
-	
+	variable marea
+	variable close_marea
+	variable tot_marea
+	variable north_start
+	variable east_start
+
 	# There is a global coords # Text to display in indicator widget, indexed by mon
 	
 	# Process ID for temp files
@@ -1601,6 +1606,11 @@
 	variable measurement_annotation_handle
 	variable mlength 
 	variable totmlength
+	variable marea
+	variable close_marea
+	variable tot_marea
+	variable north_start
+	variable east_start
 	variable linex1 
 	variable liney1 
 	variable linex2 
@@ -1635,6 +1645,11 @@
 	MapCanvas::setcursor $mon "pencil"
 	set mlength 0
 	set totmlength 0
+	set marea 0
+	set close_marea 0
+	set tot_marea 0
+	set north_start 0
+	set east_start 0
 
 }
 
@@ -1679,12 +1694,17 @@
 	}
 }
 
-# measure line length
+# measure line length and area
 proc MapCanvas::measure { mon x y } {
 	variable can
 	variable measurement_annotation_handle
 	variable mlength 
 	variable totmlength
+	variable marea
+	variable close_marea
+	variable tot_marea
+	variable north_start
+	variable east_start
 	variable linex1 
 	variable liney1 
 	variable linex2 
@@ -1714,15 +1734,41 @@
 	set mlength [expr {sqrt(pow(($east1 - $east2), 2) + pow(($north1 - $north2), 2))}]
 	set totmlength [expr {$totmlength + $mlength}]
 
+
+	# begin area calculation
+	# formula:
+	# 2A = | Sum ( ( Yi + Yi+1 ) x ( Xi - Xi+1 ) ) |
+	# save coordinates of first point of area measurement:
+	if { ($north_start == 0) && ($east_start == 0) && ($marea == 0) && \
+		($close_marea == 0) && ($tot_marea == 0)} {
+		set north_start $north1
+		set east_start $east1
+	}
+
+	#calculate and cumulate subareas
+	set marea [expr {($north1 + $north2)*($east1 - $east2) + $marea}]
+
+	#calculate last subarea (added by virtual polygon segment from last point to start point)
+	set close_marea [expr {($north2 + $north_start)*($east2 - $east_start) }]
+
+	#calculate result of area measurement
+	set tot_marea [expr { abs($marea + $close_marea) / 2}]
+
+	# end area calculation
+
+
 	# format length numbers and units in a nice way
 	set out_seg [ fmt_length $mlength ]
 	set out_tot [ fmt_length $totmlength ]
+	set out_area [ fmt_area $tot_marea ]
 
 
 	monitor_annotate $measurement_annotation_handle \
 		[G_msg " --segment length = $out_seg\n"]
 	monitor_annotate $measurement_annotation_handle \
 		[G_msg "cumulative length = $out_tot\n"]
+	monitor_annotate $measurement_annotation_handle \
+		[G_msg "             area = $out_area\n"]
 
 	set linex1 $linex2
 	set liney1 $liney2
@@ -1779,6 +1825,68 @@
 
 
 
+# format area numbers and units in a nice way, as a function of area
+proc MapCanvas::fmt_area { area } {
+
+    set mapunits [MapCanvas::get_mapunits]
+
+    set outunits $mapunits
+    set divisor "1.0"
+
+    # figure out which units to use
+    if { [string equal "meters" "$mapunits"] } {
+    	if { $area > 2500000 } {
+    	    set outunits "km2"
+    	    set divisor "1000000.0"
+    	} elseif { $area > 25000 } {
+    	    set outunits "ha"
+    	    set divisor "10000.0"
+    	} else {
+    	    set outunits "m2"
+    	    set divisor "1.0"
+    	}
+    } elseif { [string first "feet" "$mapunits"] >= 0 } {
+    	# nano-bug: we match any "feet", but US Survey feet is really
+    	#  5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
+    	#  miles the tick markers are rounded to the nearest 10th of a
+    	#  mile (528'), the difference in foot flavours is ignored.
+    	if { $area > 27878400 } {
+    	    set outunits "sq miles"
+    	    set divisor "27878400.0"
+    	} elseif { $area > 43560 } {
+    	    set outunits "acres"
+    	    set divisor "43560.0"
+    	} elseif { $area > 900 } {
+    	    set outunits "sq yards"
+    	    set divisor "9.0"
+    	} else {
+    	    set outunits "sq feet"
+    	    set divisor "1.0"
+    	}
+    } else {
+    	set outunits "unit?"
+    	set divisor "1.0"
+    }
+
+    # format numbers in a nice way
+    if { [expr $area/$divisor ] >= 2500 } {
+    	set outfmt "%.0f"
+    } elseif { [expr $area/$divisor ] >= 1000 } {
+    	set outfmt "%.1f"
+    } elseif { [expr $area/$divisor ] > 0 } {
+    	set outfmt "%.[expr {int(ceil(3 - log10($area/$divisor)))}]f"
+    } else {
+    	# error: no range (nan?)
+    	set outfmt "%g"
+    }
+
+    set outarea [format $outfmt [expr $area/$divisor ] ]
+
+    return [concat $outarea $outunits ]
+}
+
+
+
 ###############################################################################
 # procedures for querying
 
_______________________________________________
grass-dev mailing list
grass-dev@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-dev

Reply via email to