Hi
I already manage to display the raster map and read the elevation from Dted file. Now I need to plotting the point on the raster map , then it will display the distance between point just like popup. How can I achieve that?
Regards,
Fathin
Hi
I already manage to display the raster map and read the elevation from Dted file. Now I need to plotting the point on the raster map , then it will display the distance between point just like popup. How can I achieve that?
Regards,
Fathin
Hi Fathin,
You can create a InmemoryFeatureLayer and add the points into it. Then set point style for them.
But if that’s elevation data, the distance between them is in the plane or space?
I think you can show the distance as label of the line between points.
You can calculate the lines, add the distance as column value of line feature. Then when you render the map, only render the text style but not assign line style, so the distance value will be render on map directly.
About the popup you mentioned I don’t think it’s a good choice for distance, because without the line you don’t know what it point to.
Regards,
Ethan
Hi Ethan,
I don’t quite understand about InmemoryFeatureLayer features. Did you have any simple example for that?
My elevation data work just like converter, it will display the elevation when the lat long on raster map are same with lat long on Dted file. I don’t know what you mean by is in the plane or space.
CODE
namespace RasterMapViewer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{ Proj4Projection proj4Projection;
GeoTiffRasterLayer tiffLayer;
public MainWindow()
{
InitializeComponent();
}
private void Map_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.Meter;
LayerOverlay myOverlay = new LayerOverlay();
Map1.Overlays.Add(myOverlay);
myOverlay.Open();
myOverlay.TileCache = new FileBitmapTileCache(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache\");
string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Desktop\DSI REFERENCE\Map Data\Raster");
foreach (string file in files)
{
GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
myOverlay.Layers.Add(tiffLayer);
}
//Apply the projection
proj4Projection = new Proj4Projection();
proj4Projection.InternalProjectionParametersString = "+proj=omerc +lat_0=4 +lonc=102.25 +alpha=323.0257905 +k=0.99984 +x_0=804670.24 +y_0=0 +no_uoff +gamma=323.1301023611111 +a=6377295.664 +b=6356094.667915204 +units=m +no_defs"; //Current Proj in meter
proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326); //Change to the proj with decimal degree
proj4Projection.Open();
PopupOverlay popupOverlay = new PopupOverlay();
Map1.CurrentExtent = myOverlay.GetBoundingBox();
Map1.TrackOverlay.TrackMode = TrackMode.Line;
Map1.Refresh();
}
private void Map1_MouseMove(object sender, MouseEventArgs e)
{
Point point = e.MouseDevice.GetPosition(Map1);
ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.ActualWidth, (float)Map1.ActualHeight);
string x = pointShape.X.ToString("f6", CultureInfo.InvariantCulture);
string y = pointShape.Y.ToString("f6", CultureInfo.InvariantCulture);
if (proj4Projection != null)
{
//PointShape p = new PointShape(605770.08015, 388756.038425);
PointShape p2 = proj4Projection.ConvertToExternalProjection(pointShape) as PointShape;
Gdal.AllRegister(); //Register driver(s).
//string Dted = @"C:\N03.dt2";
double[] gGeoTrans = new double[6];
Dataset ds = Gdal.Open(@"C:\N03.dt2", Access.GA_ReadOnly); //Open Dataset
ds.GetGeoTransform(gGeoTrans);
OSGeo.GDAL.Band gThisBand = ds.GetRasterBand(1);
double X = Convert.ToDouble(p2.X);
double Y = Convert.ToDouble(p2.Y);
// Your query location is X, Y (both doubles), convert your location into
// local row, col addressing to specify which cell to read
int row = (int)((gGeoTrans[3] - Y) / -gGeoTrans[5]);// ULY - xcoord / -N-S CellSize;
int col = (int)((X - gGeoTrans[0]) / gGeoTrans[1]); // xcoord - ULX / E-W CellSize
// check here that the row and col are >= 0 and < gDataset.RasterXSize and
// gDataset.RasterYSize or you will get a read error.
// read the value.. reading is done to an array but as we want only one cell
// it needs to be an array of 1 float.
float[] buff = new float[1];
if ((col <= ds.RasterXSize) && col >= 0)
{
if ((row <= ds.RasterYSize) && row >= 0)
{
gThisBand.ReadRaster(col, row, 1, 1, buff, 1, 1, 0, 0); // read the cell value
}
}
else
{
return;
}
float ThisCellValue = buff[0];
TextBoxSatu.Text = "RSO_WEST(KERTAU)" + "(" + (y) + "," + " " + (x) + ")" + " " + " Lat: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(p2.Y) + "Long: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(p2.X) + " " + "Height :" + ThisCellValue + "m";
}
}
private void button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
switch (button.Name)
{
case "TrackPolygon":
Map1.TrackOverlay.TrackMode = TrackMode.Line;
break;
case "TrackNormal":
default:
Map1.TrackOverlay.TrackMode = TrackMode.None;
break;
case "TrackDelete":
Map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
tiffLayer = null;
Map1.Refresh();
break;
}
}
}
}
}
Regards,
Fathin
Hi Fathin,
Thanks for your code.
It looks the elevation value here is “ThisCellValue” and it’s related with X and Y which is mouse coordinates.
You know our layer is raster layer, it don’t read feature from data but read the image, so the points you saw on map is not point shape in layer.
So I want to double check your requirement here, what’s the scenario now?
If you want to implement #1, you can just use InmemoryFeaturelayer and render it like I mentioned in last reply.
If you want to implement #2, you can simply use TrackOverlay for it.
So what’s the mainly problem you faced here?
Regards,
Ethan
Hi Ethan,
My first problem is how can i plotting the point on map plane by using mouse click.
You have a simple example for it and what the difference of InFeatureMemoryLayer and SimpleMarkerOverlay for the point plot?
Hi Fathin,
If you want to plot points, you have to use track overlay.
After vertex added each time or track complete, you can move to points into InmemoryFeatureLayer or SimpleMarkerOverlay.
SimpleMarkerOverlay have some special feature for example popup for marker, and the InmemoryFeatureLayer is just a standard layer which is saved in memory.
About how to use the track for your scenario, I created a simple sample here:
9408.zip (102.7 KB)
You can view it and modify it for your scenario, and you can refer the other posts about it here:
Wish that’s helpful.
Regards,
Ethan
Hi Ethan,
Thank for your sample. So if i want to save the plot point i need to use InmemoryFeatureLayer right? Then how i can implement the ruler application on the point that use InmemoryFeatureLayer? My target is so that i can select an existing two point and get their distance.
Regards,
Fathin
Hi Fathin,
Yes you should want to plot points into InmemoryFeatureLayer.
If your target is select two existing points, you should want to implement this logic in your mouse click or mouse down event. You can did spatial query based on your clicked point, the nearest one point is the selected point. About how to find nearest feature based on clicked point please refer the sample here: https://github.com/ThinkGeo/GetFeaturesClickedOnSample-ForWinForms
Then you can call the spatial query API to get distance and render it on map just like my sample shows.
Wish that’s helpful.
Regards,
Ethan
Hi Ethan,
Did you have any example for the wpf ? My trial for winform already expired. May i know is there any dedicated spatial query API for mapsuite?
Regards,
Fathin
Hi Fathin,
The API for wpf and winforms is nearly the same, you can directly copy the code to wpf.
And you can find the spatial query API in QueryTools like this:
InMemoryFeatureLayer layer;
layer.QueryTools.xxx
Regards,
Ethan
Hi Ethan,
I can’t seem to create a InmemoryFeatureLayer on mouse click. It will throws me error when i start clicking the mouse on map. I want to plot a point on mouse click so that i can save it.
public partial class gdalElevation : Window
{
Proj4Projection proj4Projection;
GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer();
LayerOverlay myOverlay = new LayerOverlay();
SimpleMarkerOverlay markerOverlay = new SimpleMarkerOverlay();
PointShape p2 = new PointShape();
PointShape makePoint = new PointShape();
public gdalElevation()
{
InitializeComponent();
}
private void Map_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.Meter;
//LayerOverlay myOverlay = new LayerOverlay();
Map1.Overlays.Add(myOverlay);
myOverlay.TileCache = new FileBitmapTileCache(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache\");
string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Desktop\DSI REFERENCE\Map Data\Raster");
foreach (string file in files)
{
GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
myOverlay.Layers.Add(tiffLayer);
}
//Map1.TrackOverlay = new RulerTrackInteractiveOverlay();
myOverlay.Open();
Map1.CurrentExtent = myOverlay.GetBoundingBox();
//InMemoryFeature to show the selected feature (the feature clicked on).
InMemoryFeatureLayer selectLayer = new InMemoryFeatureLayer();
selectLayer.Open();
selectLayer.Close();
selectLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.PointType = PointType.Bitmap;
selectLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.Image = new GeoImage(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Icon\Point.png");
selectLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
//Apply the projection
proj4Projection = new Proj4Projection();
proj4Projection.InternalProjectionParametersString = "+proj=omerc +lat_0=4 +lonc=102.25 +alpha=323.0257905 +k=0.99984 +x_0=804670.24 +y_0=0 +no_uoff +gamma=323.1301023611111 +a=6377295.664 +b=6356094.667915204 +units=m +no_defs"; //Current Proj in meter
proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326); //Change to the proj with decimal degree
proj4Projection.Open();
myOverlay.Layers.Add(selectLayer);
myOverlay.TileType = TileType.MultipleTile;
myOverlay.IsBase = false;
Map1.Refresh();
}
private void Map1_MouseMove(object sender, MouseEventArgs e)
{
Point point = e.MouseDevice.GetPosition(Map1);
ScreenPointF screenPointF = new ScreenPointF((float)point.X, (float)point.Y);
PointShape pointShape = ExtentHelper.ToWorldCoordinate(Map1.CurrentExtent, screenPointF, (float)Map1.ActualWidth, (float)Map1.ActualHeight);
string x = pointShape.X.ToString("f6", CultureInfo.InvariantCulture);
string y = pointShape.Y.ToString("f6", CultureInfo.InvariantCulture);
if (proj4Projection != null)
{
//PointShape p = new PointShape(605770.08015, 388756.038425);
PointShape p2 = new PointShape();
p2 = proj4Projection.ConvertToExternalProjection(pointShape) as PointShape;
/********GDAL DTED CONVERSION*******/
Gdal.AllRegister(); //Register driver(s).
//string Dted = @"C:\N03.dt2";
double[] gGeoTrans = new double[6];
Dataset ds = Gdal.Open(@"C:\N03.dt2", Access.GA_ReadOnly); //Open Dataset
ds.GetGeoTransform(gGeoTrans);
OSGeo.GDAL.Band gThisBand = ds.GetRasterBand(1);
double X = Convert.ToDouble(p2.X);
double Y = Convert.ToDouble(p2.Y);
// Your query location is X, Y (both doubles), convert your location into
// local row, col addressing to specify which cell to read
int row = (int)((gGeoTrans[3] - Y) / -gGeoTrans[5]);// ULY - xcoord / -N-S CellSize;
int col = (int)((X - gGeoTrans[0]) / gGeoTrans[1]); // xcoord - ULX / E-W CellSize
// check here that the row and col are >= 0 and < gDataset.RasterXSize and
// gDataset.RasterYSize or you will get a read error.
// read the value.. reading is done to an array but as we want only one cell
// it needs to be an array of 1 float.
float[] buff = new float[1];
if ((col <= ds.RasterXSize) && col >= 0)
{
if ((row <= ds.RasterYSize) && row >= 0)
{
gThisBand.ReadRaster(col, row, 1, 1, buff, 1, 1, 0, 0); // read the cell value
}
}
else
{
return;
}
float ThisCellValue = buff[0];
TextBoxSatu.Text = "RSO_WEST(KERTAU)" + "(" + (y) + "," + " " + (x) + ")" + " " + " Lat: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(p2.Y) + "Long: " + DecimalDegreesHelper.GetDegreesMinutesSecondsStringFromDecimalDegree(p2.X) + " " + "Height :" + ThisCellValue + "m";
}
}
private void button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
switch (button.Name)
{
case "TrackNormal":
default:
Map1.TrackOverlay.TrackMode = TrackMode.None;
break;
case "TrackDelete":
Map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
tiffLayer = null;
Map1.Refresh();
break;
case "TrackLine":
Map1.TrackOverlay.TrackMode = TrackMode.Line;
break;
case "Marker":
Map1.TrackOverlay = new RulerTrackInteractiveOverlay();
break;
case "Point":
Map1.TrackOverlay.TrackMode = TrackMode.Point;
break;
}
}
}
private void Map1_MapClick(object sender, MapClickWpfMapEventArgs e)
{
//Here we use a buffer of 15 in screen coordinate. This means that regardless of the zoom level, we will always find the nearest feature
//within 15 pixels to where we clicked.
int screenBuffer = 10;
//Logic for converting screen coordinate values to world coordinate for the spatial query. Notice that the distance buffer for the spatial query
//will change according to the zoom level while it remains the same for the screen buffer distance.
ScreenPointF clickedPointF = new ScreenPointF(e.ScreenX, e.ScreenY);
ScreenPointF bufferPointF = new ScreenPointF(clickedPointF.X + screenBuffer, clickedPointF.Y);
double distanceBuffer = ExtentHelper.GetWorldDistanceBetweenTwoScreenPoints(Map1.CurrentExtent, clickedPointF, bufferPointF,
(float)Map1.Width,(float)Map1.Height, Map1.MapUnit, DistanceUnit.Meter);
//Adds the feature clicked on to the selected layer to be displayed as highlighed and with the name labeled.
InMemoryFeatureLayer selectLayer = (InMemoryFeatureLayer)Map1.FindFeatureLayer("SelectLayer");
//Refreshes only the select layer.
Map1.Refresh(Map1.Overlays["SelectOverlay"]);
}
}
Regards,
Fathin
Hi Fathin,
You should want to use Map1.ActualWidth and Map1.ActualHeight instead Map1.Width and Map1.Height in function Map1_MapClick.
And I suggest you build a simple sample with your code, so our developer can reproduce your exception quickly. You can build the sample based on my sample project.
Regards,
Ethan
HI Ethan,
Thank you for a reply. I will try to construct a simple sample code for the InmemoryFeatureLayer that i need to use on my project.
Regards,
Fathin
Hi Fathin,
That’s great, so we can modify based on the sample and save our communication time.
Just like I mentioned, it should be simple enough and shows the problem clearly, I think our template is a good choice for create a sample quickly: http://wiki.thinkgeo.com/wiki/map_suite_project_template_guide
Regards,
Ethan
Hi Ethan
This is a sample i just construct. I managed to plot the map using InMemoryFeatureLayer. I have this problem:
My code below throw me an exception:
KeyNotFoundException was unhandled
with remarks :
The given key was not present in the dictionary.
CODE:
namespace PointPlot
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
InMemoryFeatureLayer inmemoryFeatureLayer = new InMemoryFeatureLayer();
public MainWindow()
{
InitializeComponent();
}
private void Map1_Loaded(object sender, RoutedEventArgs e)
{
Map1.MapUnit = GeographyUnit.Meter;
LayerOverlay myOverlay = new LayerOverlay();
Map1.Overlays.Add(myOverlay);
myOverlay.TileCache = new FileBitmapTileCache(@"C:\Users\User\Documents\Visual Studio 2012\Projects\RasterMapViewer\RasterMapViewer\Cache\");
string[] files = System.IO.Directory.GetFiles(@"C:\Users\User\Desktop\DSI REFERENCE\Map Data\Raster");
foreach (string file in files)
{
GeoTiffRasterLayer tiffLayer = new GeoTiffRasterLayer(file);
myOverlay.Layers.Add(tiffLayer);
}
myOverlay.Open();
Map1.CurrentExtent = myOverlay.GetBoundingBox();
InMemoryFeatureLayer inmemoryFeatureLayer = new InMemoryFeatureLayer();
inmemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(new GeoImage(@"C:\Users\User\Documents\Visual Studio 2012\Projects\PointPlot\PointPlot\Icon\Point.png"));
//inmemoryFeatureLayer.InternalFeatures.Add("point", new Feature(@"C:\Users\User\Documents\Visual Studio 2012\Projects\PointPlot\PointPlot\Icon\Point.png"));
inmemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay markerOverlay = new LayerOverlay();
markerOverlay.Layers.Add(inmemoryFeatureLayer);
Map1.Overlays.Add("MarkerOverlay", markerOverlay);
Map1.Overlays.Add("MarkerOverlay", markerOverlay);
Map1.Refresh();
}
private void Map1_MapClick(object sender, MapClickWpfMapEventArgs e)
{
LayerOverlay markerOverlay = (LayerOverlay)Map1.Overlays["MarkerOverlay"];
InMemoryFeatureLayer inmemoryFeatureLayer = markerOverlay.Layers[0] as InMemoryFeatureLayer;
MultipolygonShape buffer = e.WorldLocation.Buffer(350, GeographyUnit.Meter, DistanceUnit.Kilometer);
inmemoryFeatureLayer.InternalFeatures.Add(new Feature(e.WorldLocation));
//Collection<Feature> deleteMarkers = inmemoryFeatureLayer.QueryTools.GetFeaturesWithin(buffer, ReturningColumnsType.NoColumns);
//if (deleteMarkers.Count > 0)
//{
// inmemoryFeatureLayer.InternalFeatures.Remove(deleteMarkers[0]);
//}
//else
//{
// inmemoryFeatureLayer.InternalFeatures.Add(new Feature(e.WorldLocation));
//}
Map1.Refresh();
}
private void Plot_ButtonClick(object sender, RoutedEventArgs e)
{
InMemoryFeatureLayer inMemoryLayer = (InMemoryFeatureLayer)Map1.FindFeatureLayer("InMemoryFeatureLayer");
inMemoryLayer.Open();
inMemoryLayer.EditTools.BeginTransaction();
inMemoryLayer.EditTools.Delete("MarkerOverlay");
inMemoryLayer.EditTools.CommitTransaction();
inMemoryLayer.Close();
Map1.Refresh(Map1.Overlays["InmemoryOverlay"]);
}
}
}
Regards,
Fathin
Hi Ethan,
If let say i create a point using marker just like in HowDoI sample, is that any a way for me to select the point so that i can edit the point or maybe get a distance in line from one marker point to another>
Regards,
Fathin
Hi Fathin,
Adjust the icon with the tooltip of mouse.
I hadn’t notice your code have related logic, do you means change the mouse cursor? or the tooltip of marker which is clicked by mouse?
How can implement button for the InMemoryFeatureLayer to enabled it, so when i start the run the it not immediately execute the InMemoryFeatureLayer for plot.
Add a bool type variable, set it’s value by a button. If it’s true just return in Map1_MapClick event, if it’s false, run your logic.
How can i delete the specific plot.
This logic should be helpful.
Collection<Feature> neartestFeatures = inmemoryFeatureLayer.QueryTools.GetFeaturesNearestTo(e.WorldLocation, GeographyUnit.Meter, 1, ReturningColumnsType.AllColumns);
if (neartestFeatures.Count > 0)
{
inmemoryFeatureLayer.InternalFeatures.Remove(neartestFeatures[0]);
}
Here is a sample project based on your code, please modify based on it, and you can upload it again to show your question instead of paste code.
15floors.zip (11.7 KB)
Regards,
Ethan
Hi Ethan,
Sorry for not clear statement regarding question (1). I mean how can i adjust so that the tooltip of icon near the tooltip of mouse cursor. Just like in using SimpleMarkerOverlay by adjusting the Yoffset, but i need to implement it on InMemoryFeatureLayer.
Sorry for paste the code i will modify the sample and upload it if i have issues with it.
Regards,
Fathin
Hi Fathin,
That related with how you implement the tooltip. I think our InmemoryFeatureLayer don’t support tooltip by default, it’s not the same like MarkerOverlay.
If you still hadn’t found the way to implement that, please refer this topic: OpenStreet Maps and WGS84 map
It contains a custom tooltip which works for winform, but I think you can try to use it in WPF and see whether it works for your requirement.
Regards,
Ethan
HI Ethan,
May i know how can i make a selection for the inmemoryfeaturelayer? What i mean i can select the point that just been created using InmemoryFeatureLayer. In addition, can you check this code? I try copy exactly the same code from HowDoI sample for delete the feature in InmemoryFeatureLayer. It does not delete the rectangle feature.
Regards,
Fathin