LabelDecon.sml

  Download

More scripts: Enhanced Data Tip

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
class GRE_GROUP g_group =MainLayout.GetGroupByName("Group 1");
class GRDEVICE_MEM_RGB24 imgdev;
class GRDEVICE_MEM_BINARY maskdev;
class GC imagegc, maskgc;
class GRE_GROUP group;
proc OnLayoutDrawEnd (
   class GRE_LAYOUT layout,
	class GRE_VIEW view
   ) {
	group = layout.GetGroupByName("ProvinceMaps");
	g_group = group;
   }
func OnViewDataTipShowRequest (
	class GRE_VIEW view,
	class POINT2D point,		# Point in screen coordinates
	class TOOLTIP datatip
	) {
	datatip.Delay = 500;
	datatip.String = "";
	local class GRE_LAYER layer = g_group.FirstLayer;
	local class LABELPLACE place, places[];
	local class GRE_LABELS labels;
	local class POINT2D offset, delta, oldcenter, newpt, groupcenter, groupdelta, center;
	local class REGION2D reg, groupreg;
	local class RECT extents, groupextents, oldextents;
	local numeric zoom = 2.0, q, angle, SolutionFound, dTheta;
	local class POINT2D offsets[];
	local class LABELATTACHMENT attachment;
	local class POLYLINE leader;
	local class COLOR foregroundcolor;
	foregroundcolor.name = "red2";
	offset.x = 10;	# Offset so label doesn't fall under cursor
	offset.y = 10;
	imagegc = imgdev.CreateGC();
	while (layer) {
		labels = layer.GetLabels(view);
		labels.GetItemAtLocation(point, place, 10);
		reg = place.GetRegion();
		places = labels.GetItemsOverlappingRegion(reg);
		numeric number = places.GetNumItems();
		if (number > 1) {
			# Find the extents of the labels as they are on the screen
			groupreg.Clear();
			for q = 1 to number {
				groupreg.UnionRegion(places[q].GetRegion());
				}
			groupextents = groupreg.Extents;
			groupcenter = groupextents.center;
			# Expand the extents so that our labels will be placed far enough
			# out for their leader lines to look good
			groupextents.Expand(10, 10);
			# Compute zoomed extents so we know how big to make our window
			# and decide where we'll place the labels while we're at it
			reg.Clear();
			for q = 1 to number {
				place = places[q];
				center = place.GetRegion().Extents.center;
				angle = groupcenter.GetAngle(center);
				# Remove the leaders so we don't try to zoom them
				place.SetCopyOnWrite(1);
				while (place.GetNumAttachments()) {
				 	 place.DeleteAttachment(place.GetAttachment(1).Element);
					 }
			   zoom = 30 / place.GetRegion().Extents.GetHeight();
				if (zoom < 1.0) zoom = 1.0;
			  	place.Zoom(zoom);
				dTheta = 0;
				SolutionFound = false;
				while (!SolutionFound && dTheta < 360) {
					# Move out from center until label no longer intersects
					# the extents of the actual labels
					delta.x = cos(angle);
					delta.y = sin(angle);
					extents = place.GetRegion().Extents;
					offset.x = groupcenter.x - extents.center.x;
					offset.y = groupcenter.y - extents.center.y;
					extents += offset;
					while (groupextents.Overlaps(extents)) {
						offset += delta;
						extents += delta;
						}
					# Make sure this label won't overlap another one.  If it will,
					# move 10 degrees around and try again.  If we get all the
					# way around the circle and still can't find a spot, give up.
					SolutionFound = reg.TestRect(extents, "FullOutside");
					if (!SolutionFound) {
						dTheta += 10;
						angle += 10 / deg;
						}
					}
				offsets[q] = offset;
				place.Move(offset);
				reg.UnionRegion(place.GetRegion());
				}
			groupdelta.x = -reg.Extents.x1;
			groupdelta.y = -reg.Extents.y1;
			imgdev.Create(reg.Extents.GetHeight()+5,reg.Extents.GetWidth()+5);
			imgdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters);
			imgdev.Clear("white");
			imagegc = imgdev.CreateGC();
			imagegc.SetOutputScale(view.GetMapScale());
			maskdev.Create(imgdev.GetHeight(),imgdev.GetWidth());
			maskdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters);
			maskdev.ClearAll();
			maskgc = maskdev.CreateGC();
			maskgc.SetOutputScale(view.GetMapScale());
			maskgc.SetPixelFunction("Set");
			for q = 1 to number {
				place = places[q];
				oldextents = place.GetRegion().Extents;
				center = oldextents.center;
				oldextents += groupdelta;
				center += groupdelta;
				place.SetCopyOnWrite(1);
				# Remove the leaders so we don't try to zoom them
				while (place.GetNumAttachments()) {
				 	 place.DeleteAttachment(place.GetAttachment(1).Element);
					 }
			   zoom = 30 / place.GetRegion().Extents.GetHeight();
				if (zoom < 1.0) zoom = 1.0;
			  	place.Zoom(zoom);
				extents = place.GetRegion().Extents;
				delta = offsets[q] + groupdelta;
				extents += delta;
				newpt = extents.center;
				place.Move(delta);
				leader.Clear();
				leader.AppendVertex(center);
				leader.AppendVertex(newpt);
				attachment.Leader = leader;
				place.AddAttachment(attachment);
				# Draw the label to use as an image tip
				place.DrawSample(imagegc, foregroundcolor);
				# Draw again into a mask device
				place.DrawSample(maskgc, foregroundcolor);
				}
		 	# Figure out where to place the tip
		 	newpt.x = -groupdelta.x;
		 	newpt.y = -groupdelta.y;
		 	offset = newpt - point;
			# Show the tip
			datatip.SetImageTip(imgdev, maskdev, offset);
			return (1);
			}
		else {  # Single data tip case
			place = places[1];
			extents = place.GetRegion().Extents;
			oldcenter = extents.center;
			# Make sure we're modifying a COPY of the place, not the original
			place.SetCopyOnWrite(1);
			# Remove the leaders so we don't try to zoom them
			while (place.GetNumAttachments()) {
				place.DeleteAttachment(place.GetAttachment(1).Element);
				}
			zoom = 30 / place.GetRegion().Extents.GetHeight();# THIS IS CATCHING THE LABEL SIZE, IF IT IS SMALLER THAN 1, DON'T DO BELOW...
			# Zoom it up.  Maybe compute a zoom factor based on current size?
			if (zoom > 1.2) {
				place.Zoom(zoom);
				# Get new extents
				extents = place.GetRegion().Extents;
				# Move the label to (0,0)
				delta.x = -extents.x1;
				delta.y = -extents.y1;
				place.Move(delta);
				# Draw the label to use as an image tip
				imgdev.Create(extents.GetHeight()+2, extents.GetWidth()+2);
				imgdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters);
				imgdev.Clear("white");
				imagegc = imgdev.CreateGC();
				imagegc.SetOutputScale(view.GetMapScale());
				place.DrawSample(imagegc,foregroundcolor);
				# Draw again into a mask device
				maskdev.Create(imgdev.GetHeight(),imgdev.GetWidth());
				maskdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters);
				maskdev.ClearAll();
				maskgc = maskdev.CreateGC();
				maskgc.SetOutputScale(view.GetMapScale());
				maskgc.SetPixelFunction("Set");
				place.DrawSample(maskgc, foregroundcolor);
				# Figure out where to place the tip
				newpt.x = oldcenter.x - imgdev.GetWidth() / 2;
				newpt.y = oldcenter.y - imgdev.GetHeight() / 2;
				offset = newpt - point;
				# Show the tip
				datatip.SetImageTip(imgdev, maskdev, offset);
				return (1);
				}
			}
		layer = layer.NextLayer;
		}
	return (0);
	}
proc OnViewDataTipHidden (
   class GRE_VIEW view
   ) {
   # Insert code here
   }