using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace DisplayingOneWayStreets
{
//Displays an arrow (GeoImage) if the value (OneWayValue) is one-way in the column OnWayColumnName.
//Shows the arrow in the direction of the vertices of the line records.
class OneWayLineStyle : LineStyle
{
private string oneWayColumnName;
private string oneWayValue;
private GeoImage geoImage;
public OneWayLineStyle()
: this(string.Empty, string.Empty, new GeoImage())
{ }
public OneWayLineStyle (string oneWayColumnName, string oneWayValue, GeoImage geoImage)
{
this.oneWayColumnName = oneWayColumnName;
this.oneWayValue = oneWayValue;
this.geoImage = geoImage;
}
public string OneWayColumnName
{
get { return oneWayColumnName; }
set { oneWayColumnName = value; }
}
public string OneWayValue
{
get { return oneWayValue; }
set { oneWayValue = value; }
}
//Image representing the arrow.
//The arrow of the image should be pointing to the top to have the function GetAngleFromTwoVertices working adequately.
public GeoImage GeoImage
{
get { return geoImage; }
set { geoImage = value; }
}
protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
{
//Loops thru the features to draw the one way feature with the geoImage (arrow)
foreach (Feature feature in features)
{
string currentOneWayValue = Convert.ToString(feature.ColumnValues[oneWayColumnName]);
if (currentOneWayValue == oneWayValue)
{
MultilineShape multilineShape = (MultilineShape)feature.GetShape();
//Gets the LineShape made of the two vertices of the longest segment for displaying the arrow image on it.
LineShape lineShape = GetLongestSegment(multilineShape);
//Gets the angle based on the two vertices of the longest segment.
double angle = GetAngleFromTwoVertices(lineShape.Vertices[0], lineShape.Vertices[1]);
//Gets the PointShape in the middle of the longest segment to center the arrow image on.
PointShape pointShape = lineShape.GetPointOnALine(StartingPoint.FirstPoint,50);
canvas.DrawWorldImage(geoImage, pointShape.X, pointShape.Y, geoImage.GetWidth(), geoImage.GetHeight(),DrawingLevel.LevelFour,0,0 , (float)angle);
}
}
}
private LineShape GetLongestSegment(MultilineShape multiLineShape)
{
LineShape resultLineShape = new LineShape();
double longestDist = 0;
foreach (LineShape lineShape in multiLineShape.Lines)
{
for (int i = 0; i < lineShape.Vertices.Count - 2; i++)
{
PointShape pointShape1 = new PointShape(lineShape.Vertices[i]);
PointShape pointShape2 = new PointShape(lineShape.Vertices[i|+ 1]);
double currentDist = pointShape1.GetDistanceTo(pointShape2, GeographyUnit.Meter, DistanceUnit.Meter);
if (currentDist > longestDist)
{
resultLineShape.Vertices.Clear();
resultLineShape.Vertices.Add(lineShape.Vertices[i]);
resultLineShape.Vertices.Add(lineShape.Vertices[i|+ 1]);
longestDist = currentDist;
}
}
}
return resultLineShape;
}
private double GetAngleFromTwoVertices(Vertex b, Vertex c)
{
double alpha = 0;
double tangentAlpha = (c.Y - b.Y) / (c.X - b.X);
double Peta = Math.Atan(tangentAlpha);
if (c.X > b.X)
{
alpha = 90 + (Peta * (180 / Math.PI));
}
else if (c.X < b.X)
{
alpha = 270 + (Peta * (180 / Math.PI));
}
else
{
if (c.Y > b.Y) alpha = 0;
if (c.Y < b.Y) alpha = 180;
}
return alpha;
}
protected override Collection<string> GetRequiredColumnNamesCore()
{
Collection<string> columns = new Collection<string>();
if (!columns.Contains(oneWayColumnName))
{
columns.Add(oneWayColumnName);
}
return columns;
}
}
}
using System;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
namespace DisplayingOneWayStreets
{
public partial class TestForm : Form
{
private MapEngine mapEngine = new MapEngine();
private Bitmap bitmap = null;
public TestForm()
{
InitializeComponent();
}
private void TestForm_Load(object sender, EventArgs e)
{
// Set the extent and the background color
mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-97.77,30.30,-97.75,30.29), Map.Width, Map.Height);
mapEngine.BackgroundFillBrush = new GeoSolidBrush(GeoColor.FromArgb(255,237,234,226));
//Adds the street Layer for Austin
ShapeFileFeatureLayer austinStreetsShapeLayer = new ShapeFileFeatureLayer(@"..\..\Data\AustinWithOneWayRoad.shp");
austinStreetsShapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
//Adds the first LineStyle for displaying the streets
austinStreetsShapeLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(LineStyles.LocalRoad1);
//Adds the second LineStyle of type OneWayLineStyle for displaying the arrow (geoImage) according to the street direction.
OneWayLineStyle oneWayLineStyle = new OneWayLineStyle("ONE_WAY","1", new GeoImage(@"..\..\Data\Arrow_up.png"));
austinStreetsShapeLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(oneWayLineStyle);
ShapeFileFeatureLayer austinStreetsLabelLayer = new ShapeFileFeatureLayer(@"..\..\Data\AustinWithOneWayRoad.shp");
austinStreetsLabelLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(TextStyles.LocalRoad1("FENAME"));
austinStreetsLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
mapEngine.StaticLayers.Add("StreetLayer", austinStreetsShapeLayer);
mapEngine.StaticLayers.Add("StreetLayerLabel", austinStreetsLabelLayer);
DrawImage();
}
private void DrawImage()
{
if (bitmap != null) { bitmap.Dispose(); }
bitmap = new Bitmap(Map.Width, Map.Height);
mapEngine.OpenAllLayers();
mapEngine.DrawStaticLayers(bitmap, GeographyUnit.DecimalDegree);
mapEngine.DrawDynamicLayers(bitmap, GeographyUnit.DecimalDegree);
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();
}
private void Map_MouseMove(object sender, MouseEventArgs e)
{
//Displays the X and Y in screen coordinates.
statusStrip1.Items["toolStripStatusLabelScreen"].Text = "X:" + e.X + " Y:" + e.Y;
//Gets the PointShape in world coordinates from screen coordinates.
PointShape pointShape = ExtentHelper.ToWorldCoordinate(mapEngine.CurrentExtent, new ScreenPointF(e.X, e.Y), Map.Width, Map.Height);
//Displays world coordinates.
statusStrip1.Items["toolStripStatusLabelWorld"].Text = "(world) X:" + Math.Round(pointShape.X, 4) + " Y:" + Math.Round(pointShape.Y, 4);
}
}
}