using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace HybridTextStyle
{
public class HybridTextStyle : TextStyle
{
private Dictionary<string, double> rotationAngles;
public HybridTextStyle()
: base()
{
rotationAngles = new Dictionary<string, double>();
}
public HybridTextStyle(string textColumnName, GeoFont textFont, GeoSolidBrush textSolidBrush)
: base(textColumnName, textFont, textSolidBrush)
{
rotationAngles = new Dictionary<string, double>();
}
public Dictionary<string, double> RotationAngles
{
get { return rotationAngles; }
set { rotationAngles = value; }
}
protected override Collection<LabelingCandidate> GetLabelingCandidateCore(Feature feature, GeoCanvas canvas)
{
Collection<LabelingCandidate> labelingCandidates = base.GetLabelingCandidateCore(feature, canvas);
if (rotationAngles.ContainsKey(feature.Id))
{
foreach (LabelingCandidate item in labelingCandidates)
{
item.LabelInformation[0].RotationAngle += rotationAngles[feature.Id];
}
}
return labelingCandidates;
}
protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
{
// Loop through all of the features being passed in to draw.
//Notice that for the drawing, it calls base.DrawCore from the base class meaning that all the properties such as Overlapping, Duplicate rules etc
//are taken into account.
foreach (Feature feature in features)
{
// This gets the bounding box for the feature.
RectangleShape boundingBox = feature.GetBoundingBox();
//Gets the bounding box of the feature in screen coordinates.
double boundingBoxScreenWidth = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(canvas.CurrentWorldExtent,
new PointShape(boundingBox.UpperLeftPoint.X, (boundingBox.UpperLeftPoint.Y + boundingBox.LowerLeftPoint.Y) / 2),
new PointShape(boundingBox.LowerRightPoint.X, (boundingBox.UpperRightPoint.Y + boundingBox.LowerRightPoint.Y) / 2),
canvas.Width, canvas.Height);
string text = feature.ColumnValues[TextColumnName];
DrawingRectangleF drawingRectangleF = canvas.MeasureText(text, this.Font);
//Compares the bounding box in screen coordinates with the size of the text.
if (boundingBoxScreenWidth > drawingRectangleF.Width)
{
//If fully within, it draws in one line.
base.DrawCore(new Feature[1] { feature }, canvas, labelsInThisLayer, labelsInAllLayers);
}
else
{
//If not, applies the word wrapping.
string[] Words = Wrap(text, GetMaxStringLength(canvas, drawingRectangleF.Width));
string newLineText = "";
for (int i = 0; i < Words.Length; i++)
{
newLineText = newLineText + Words[i] + Environment.NewLine;
}
feature.ColumnValues[TextColumnName] = newLineText;
base.DrawCore(new Feature[1] { feature }, canvas, labelsInThisLayer, labelsInAllLayers);
}
}
}
//Function to get the maximum length of the string without having a new line.
private int GetMaxStringLength(GeoCanvas canvas, float currentWidth)
{
//For now, the value is 10. You can write your own logic to calculate that value based on
// the size of the text and the bounding box to hold it.
int result = 10;
return result;
}
//Function taken from http://www.velocityreviews.com/forums/t20370-word-wrap-line-break-code-and-algorithm-for-c.html
private string[] Wrap(string text, int maxLength)
{
text = text.Replace("\n", " ");
text = text.Replace("\r", " ");
text = text.Replace(".", ". ");
text = text.Replace(">", "> ");
text = text.Replace("\t", " ");
text = text.Replace(",", ", ");
text = text.Replace(";", "; ");
text = text.Replace("
", " ");
text = text.Replace(" ", " ");
string[] Words = text.Split(' ');
int currentLineLength = 0;
ArrayList Lines = new ArrayList(text.Length / maxLength);
string currentLine = "";
bool InTag = false;
foreach (string currentWord in Words)
{
//ignore html
if (currentWord.Length > 0)
{
if (currentWord.Substring(0, 1) == "<")
InTag = true;
if (InTag)
{
//handle filenames inside html tags
if (currentLine.EndsWith("."))
{
currentLine += currentWord;
}
else
currentLine += " " + currentWord;
if (currentWord.IndexOf(">") > -1)
InTag = false;
}
else
{
if (currentLineLength + currentWord.Length + 1 < maxLength)
{
currentLine += " " + currentWord;
currentLineLength += (currentWord.Length + 1);
}
else
{
Lines.Add(currentLine);
currentLine = currentWord;
currentLineLength = currentWord.Length;
}
}
}
}
if (currentLine != "")
Lines.Add(currentLine);
string[] textLinesStr = new string[Lines.Count];
Lines.CopyTo(textLinesStr, 0);
return textLinesStr;
}
protected override System.Collections.ObjectModel.Collection<string> GetRequiredColumnNamesCore()
{
// Here we grab the column from the textStyle and then add
// the required columns to make sure we pull back the column
// that we need for labeling.
Collection<string> columns = new Collection<string>();
if (!columns.Contains(TextColumnName))
{
columns.Add(TextColumnName);
}
return columns;
}
}
}
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using ThinkGeo.MapSuite.Core;
namespace HybridTextStyle
{
public partial class TestForm : Form
{
private MapEngine mapEngine = new MapEngine();
private Bitmap bitmap = null;
private Dictionary<string, double> angles;
double angle1;
double angle2;
private InMemoryFeatureLayer inMemoryFeatureLayer;
private HybridTextStyle hybridTextStyle;
public TestForm()
{
InitializeComponent();
}
private void TestForm_Load(object sender, EventArgs e)
{
// Sets the full extent and the background color.
mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-124.0625, 289.140625, 354.0625, -89.140625), Map.Width, Map.Height);
mapEngine.BackgroundFillBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean);
//Sets the HybridTexStyle for the InMemoryFeatureLayer.
hybridTextStyle = new HybridTextStyle("name", new GeoFont("Arial", 10), new GeoSolidBrush(GeoColor.StandardColors.DarkOliveGreen));
angles = new Dictionary<string, double>();
hybridTextStyle.RotationAngles = angles;
inMemoryFeatureLayer = new InMemoryFeatureLayer();
inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1;
inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = hybridTextStyle;
inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
inMemoryFeatureLayer.Open();
inMemoryFeatureLayer.Columns.Add(new FeatureSourceColumn("name"));
inMemoryFeatureLayer.Close();
PolygonShape polygonShape1 = new PolygonShape();
polygonShape1.OuterRing.Vertices.Add(new Vertex(0, 30));
polygonShape1.OuterRing.Vertices.Add(new Vertex(100, 30));
polygonShape1.OuterRing.Vertices.Add(new Vertex(100, 0));
polygonShape1.OuterRing.Vertices.Add(new Vertex(0,0));
polygonShape1.OuterRing.Vertices.Add(new Vertex(0, 30));
Feature feature1 = new Feature(polygonShape1);
feature1.ColumnValues.Add("name", "Horadric Cube");
inMemoryFeatureLayer.InternalFeatures.Add("Shape1",feature1);
PolygonShape polygonShape2 = new PolygonShape();
polygonShape2.OuterRing.Vertices.Add(new Vertex(150, 200));
polygonShape2.OuterRing.Vertices.Add(new Vertex(230, 200));
polygonShape2.OuterRing.Vertices.Add(new Vertex(230, 110));
polygonShape2.OuterRing.Vertices.Add(new Vertex(150,110));
polygonShape2.OuterRing.Vertices.Add(new Vertex(150,200));
Feature feature2 = new Feature(polygonShape2);
feature2.ColumnValues.Add("name", "Pandora Box");
inMemoryFeatureLayer.InternalFeatures.Add("Shape2",feature2);
mapEngine.DynamicLayers.Add("Shapes",inMemoryFeatureLayer);
DrawImage();
}
private void btnRotate1_Click(object sender, EventArgs e)
{
angle1 = angle1 + 10;
RotateShape("Shape1", angle1);
DrawImage();
}
private void btnRotate2_Click(object sender, EventArgs e)
{
angle2 = angle2 + 10;
RotateShape("Shape2", angle2);
DrawImage();
}
private void btnSizeUp1_Click(object sender, EventArgs e)
{
ScaleUp("Shape1");
DrawImage();
}
private void btnSizeUp2_Click(object sender, EventArgs e)
{
ScaleUp("Shape2");
DrawImage();
}
private void btnSizeDown1_Click(object sender, EventArgs e)
{
ScaleDown("Shape1");
DrawImage();
}
private void btnSizeDown2_Click(object sender, EventArgs e)
{
ScaleDown("Shape2");
DrawImage();
}
private void RotateShape(string key, double angle)
{
Feature feature = inMemoryFeatureLayer.InternalFeatures[key];
PolygonShape polygonShape = feature.GetShape() as PolygonShape;
polygonShape.Rotate(polygonShape.GetCenterPoint(), 10);
polygonShape.Id = key;
angles[key] = angle;
inMemoryFeatureLayer.Open();
inMemoryFeatureLayer.EditTools.BeginTransaction();
inMemoryFeatureLayer.EditTools.Update(polygonShape);
inMemoryFeatureLayer.EditTools.CommitTransaction();
inMemoryFeatureLayer.Close();
}
private void ScaleUp(string key)
{
Feature feature = inMemoryFeatureLayer.InternalFeatures[key];
PolygonShape polygonShape = feature.GetShape() as PolygonShape;
polygonShape.ScaleUp(10);
polygonShape.Id = key;
inMemoryFeatureLayer.Open();
inMemoryFeatureLayer.EditTools.BeginTransaction();
inMemoryFeatureLayer.EditTools.Update(polygonShape);
inMemoryFeatureLayer.EditTools.CommitTransaction();
inMemoryFeatureLayer.Close();
}
private void ScaleDown(string key)
{
Feature feature = inMemoryFeatureLayer.InternalFeatures[key];
PolygonShape polygonShape = feature.GetShape() as PolygonShape;
polygonShape.ScaleDown(10);
polygonShape.Id = key;
inMemoryFeatureLayer.Open();
inMemoryFeatureLayer.EditTools.BeginTransaction();
inMemoryFeatureLayer.EditTools.Update(polygonShape);
inMemoryFeatureLayer.EditTools.CommitTransaction();
inMemoryFeatureLayer.Close();
}
private void DrawImage()
{
if (bitmap != null) { bitmap.Dispose(); }
bitmap = new Bitmap(Map.Width, Map.Height);
mapEngine.OpenAllLayers();
mapEngine.DrawStaticLayers(bitmap, GeographyUnit.Meter);
mapEngine.DrawDynamicLayers(bitmap, GeographyUnit.Meter);
mapEngine.CloseAllLayers();
Map.Image = bitmap;
}
private void ToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
{
switch (e.Button.Tag.ToString())
{
case "Zoom In":
mapEngine.CurrentExtent.ScaleDown(50);
break;
case "Zoom Out":
mapEngine.CurrentExtent.ScaleUp(50);
break;
case "Full Extent":
mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-180.0, 83.0, 180.0, -90.0), Map.Width, Map.Height);
break;
case "Pan Left":
mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Left, 20);
break;
case "Pan Right":
mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Right, 20);
break;
case "Pan Up":
mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Up, 20);
break;
case "Pan Down":
mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Down, 20);
break;
default:
break;
}
DrawImage();
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
}
}