So what I am trying to do is showing a route on a winforms application using the GMap.NET nugget.
But the problem I encountered is that it doesn't show the route using the roads. It's literately showing the shortest distances between 2 points, so to make it more accurate I did an extra API call to google maps Directions. So I have some extra points to make it more accurate but still between 2 points its just a straight line, not on roads.
route problem
Here you can see how I am loading the points.
public void ShowRoute(Coordinate[] coordinates)
{
if (coordinates.Length > 1)
{
List<PointLatLng> points = new List<PointLatLng>();
foreach (var cor in coordinates)
{
Coordinate c = geo.ConvertCoordinates(cor);
var corstring = geo.GetAdresByCor(c);
var point = new PointLatLng(Convert.ToDouble(c.Latitude.Replace(".", ",")), Convert.ToDouble(c.Longitude.Replace(".", ",")));
var marker = new GMarkerGoogle(point, GMarkerGoogleType.pink_pushpin);
routeMarkers.Markers.Add(marker);
}
var routes = geo.DirectionsByCor(coordinates);
foreach (var route in routes)
{
foreach (var step in route.Legs[0].Steps)
{
var point = new PointLatLng(step.EndLocation.Latitude, step.EndLocation.Longitude);
points.Add(point);
}
}
var r = new GMapRoute(points, "route");
var routesOverlay = new GMapOverlay("routes");
routesOverlay.Routes.Add(r);
map.Overlays.Add(routeMarkers);
map.Overlays.Add(routesOverlay);
}
}
Here is how my Map is loaded.
private void map_Load(object sender, EventArgs e)
{
GMapProviders.GoogleMap.ApiKey = Properties.Settings.Default.ApiKey;
geo = new GeocoderXY();
map.MouseWheelZoomEnabled = true;
map.DragButton = MouseButtons.Left;
map.MapProvider = GMapProviders.GoogleMap;
lng = 3.7074218;
lat = 51.008157;
GMapMarker marker = new GMarkerGoogle(new PointLatLng(lat, lng), GMarkerGoogleType.blue_pushpin);
searchMarker = marker;
markers.Markers.Add(marker);
markers.Markers.Add(mouseMarker);
map.Position = new NET.PointLatLng(lat, lng);
map.MouseWheelZoomType = NET.MouseWheelZoomType.MousePositionWithoutCenter;
map.MinZoom = 5;
map.MaxZoom = 100;
map.Zoom = 15;
map.ShowCenter = false;
}
I don't see what I'm doing wrong, if someone does see it, please let me know!
Thanks
Still it's not clear why you're doing extra calls.Anyway, to get a route all it's needed a start and end locations and call GetDirections (apparently GoogleMapProvider is obsolete):
GDirections myDirections;
var route = GMapProviders.GoogleMap.GetDirections(out myDirections, start, end, false, false, false, false, false);
then use the directions to draw
var route = new GMapRoute(myDirections.Route, "route");
var routesOverlay = new GMapOverlay("routes");
routesOverlay.Routes.Add(route);
Unfortunately I dont have the VS to test but you got the idea.
Related
I am trying to split a LinearRing into multiple LinearRings using multiple lines. The expected result is a collection of LinearRings (as in the attached image). Expected result is here attached in the image. (https://i.stack.imgur.com/Kuzr8.jpg) I am not understanding how to call the recursive function. Below is the code I tried.
If it was one single line which was cutting the polygon, I could have done that. But the problem here is that we have multiple linesstrings cutting the polygon, into multiple 'pieces'. Also, I know that each time if the current line is cutting and making two pieces of the current polygon, the current polygon should be removed from the final result. This seems a bit complicated for me.
The Main Function:
static void Main(string[] args)
{
Coordinate c22 = new Coordinate(2889.0, 1277.0);
Coordinate c23 = new Coordinate(2894.0, 1288.0);
Coordinate c24 = new Coordinate(2901.0, 1284.0);
Coordinate c25 = new Coordinate(2909.0, 1289.0);
Coordinate c26 = new Coordinate(2916.0, 1281.0);
Coordinate c27 = new Coordinate(2912.0, 1270.0);
Coordinate c28 = new Coordinate(2906.0, 1275.0);
Coordinate c29 = new Coordinate(2898.0, 1273.0);
LinearRing outerBoundary = new LinearRing(new Coordinate[] { c22, c23, c24, c25, c26, c27, c28, c29, c22 });
List<LineString> lines = new List<LineString>();
Coordinate p30 = new Coordinate(2892.0, 1270.0);
Coordinate p31 = new Coordinate(2900.0, 1294.0);
LineString ln1 = new LineString(new Coordinate[] { p30, p31 });
lines.Add(ln1);
Coordinate p32 = new Coordinate(2909.0, 1268.0);
Coordinate p33 = new Coordinate(2907.0, 1294.0);
LineString ln2 = new LineString(new Coordinate[] {p32, p33});
lines.Add(ln2);
Coordinate p34 = new Coordinate(2886.0, 1286.0);
Coordinate p35 = new Coordinate(2922.0, 1278.0);
LineString ln3 = new LineString(new Coordinate[] {p34, p35});
lines.Add(ln3);
Coordinate p36 = new Coordinate(2883.0, 1281.0);
Coordinate p37 = new Coordinate(2923.0, 1273.0);
LineString ln4 = new LineString(new Coordinate[] {p36, p37});
lines.Add(ln4);
Geometry polygons = CookieCutter(outerBoundary, new List<LineString>() { ln1, ln2, ln3, ln4 });
}
The Recursive function. This is where I am stuck;
public static Geometry CookieCutter(LinearRing polygon, List<LineString> cuttingEdges, Geometry pieces = null)
{
if (pieces == null) { pieces = Polygonize(polygon.Union(cuttingEdges[0])); }
foreach (var cuttingEdge in cuttingEdges)
{
for (int i = 0; i < pieces.NumGeometries; i++)
{
pieces = pieces.GetGeometryN(i);
Geometry newPieces = Polygonize(polygon.Union(cuttingEdge));
// I know somewhere here it should call CookieCutter on new pieces
// But how to...?
}
}
}
Here is the function to polygonize;
public static Geometry Polygonize(Geometry geometry)
{
var lines = LineStringExtracter.GetLines(geometry);
var polygonizer = new Polygonizer(false);
polygonizer.Add(lines);
var polys = new List<Geometry>(polygonizer.GetPolygons());
var polyArray = GeometryFactory.ToGeometryArray(polys);
return geometry.Factory.BuildGeometry(polyArray);
}
Ohh... the solution was simple. I was trying to complicate it unnecessarily. There was no need of any recursion. I resolved it like this;
public static Geometry CookieCutter(
Geometry polygon,
List<LineString> cuttingEdges
)
{
MultiLineString mls = new MultiLineString(cuttingEdges.ToArray());
var union = polygon.Union(mls);
var polygons = Polygonize(union);
return polygons;
}
I am having an issue where my UISearchBar does not resize on phone rotation unless I touch on the search bar so that it has focus (see images below).
The search bar is created and added to a UIMapView as a subview. See code.
Searchbar creation:
public UISearchController DefineSearchController()
{
_searchResultsController = new SearchResultsVC(_mapView);
_searchResultsController.searchItemSelected += PlaceSelect;
_searchUpdater = new SearchResultsUpdator();
_searchUpdater.UpdateSearchResults += _searchResultsController.Search;
//add the search controller
var searchController = new UISearchController(_searchResultsController)
{
SearchResultsUpdater = _searchUpdater
};
var scb = searchController.SearchBar;
scb.SizeToFit();
scb.SearchBarStyle = UISearchBarStyle.Minimal;
var img = UIImage.FromBundle("tabSpace");
scb.SetBackgroundImage(img, UIBarPosition.Top, UIBarMetrics.Default);
var textField = scb.ValueForKey(new NSString("searchField")) as UITextField;
if (textField != null)
{
var backgroundView = textField.Subviews[0];
if (backgroundView != null)
{
backgroundView.BackgroundColor = UIColor.White;
backgroundView.Layer.BorderColor = AppColour.PersianBlue.GetUIColour().CGColor;
backgroundView.Layer.BorderWidth = 1;
backgroundView.Layer.CornerRadius = 10;
backgroundView.ClipsToBounds = true;
}
}
var localEnterPoI = NSBundle.MainBundle.LocalizedString("placeHolderSearchForLocation", "Enter a PoI to search for");
scb.Placeholder = localEnterPoI;
searchController.Delegate = new SearchControllerDelegate();
searchController.HidesNavigationBarDuringPresentation = false;
return searchController;
}
Added to the subview:
//Define Search Controller
_mapSearchManager = new MapSearchManager(_mapView);
_searchController = _mapSearchManager.DefineSearchController();
var scb = _searchController.SearchBar;
_mapView.AddSubview(scb);
NSLayoutConstraint.ActivateConstraints(new NSLayoutConstraint[]{
scb.TopAnchor.ConstraintEqualTo(_mapView.TopAnchor, 30),
scb.LeadingAnchor.ConstraintEqualTo(_mapView.LeadingAnchor, 10),
scb.TrailingAnchor.ConstraintEqualTo(_mapView.LeadingAnchor, -10),
});
I heave search extensively and was only able to find one similar issue:
UISearchBar doesn't resize when frame is resized in IOS 11
I implementing both of suggestion but it didn't make any difference.
Has anyone else encounted this or know what a possible solution might be.
Cheers
I've got a question regarding animations for WPF in C# code!
I have an handler function for the MouseWheel event. It just checks if you 'zoomed in' or 'zoomed out'. Just have a look at the code, the important line here is the 4th line, where the RenderTransform is set.
private void ZoomPanCanvas_MouseWheel(object sender, MouseWheelEventArgs e) {
var factor = (e.Delta > 0) ? (1.1) : (1 / 1.1);
currrentScale = factor * currrentScale;
mNetworkUI.RenderTransform = new ScaleTransform(currrentScale, currrentScale);
var pos = e.GetPosition(mNetworkUI);
mNetworkUI.Width = ZoomPanCanvas.ActualWidth / currrentScale;
mNetworkUI.Height = ZoomPanCanvas.ActualHeight /currrentScale;
var dummyTransform = new ScaleTransform(factor, factor, pos.X, pos.Y);
var offSet = new Point(dummyTransform.Value.OffsetX, dummyTransform.Value.OffsetY);
mNetworkUI.ViewModel.Network.SetTransformOffset(offSet);
}
I kept the rest of the function in the code for completeness.
What I want to do, is to animate this change of the RenderTransform!
I already tried to use a Storyboard (with UIElement.RenderTransformProperty set). Best result was a not-animated change of the RenderTransform (but it was not the same result as this 4th line from the code achieves).
Maybe you can help me, I already tried a few suggested methods from the other questions here.
Edit:
Here's the non-working attempt and at first the chenged code from above:
private void ZoomPanCanvas_MouseWheel(object sender, MouseWheelEventArgs e) {
var factor = (e.Delta > 0) ? (1.1) : (1 / 1.1);
currrentScale = factor * currrentScale;
///mNetworkUI.RenderTransform = new ScaleTransform(currrentScale, currrentScale);
Helper.Animations.RenderTransformAnimation(mNetworkUI, new ScaleTransform(currrentScale, currrentScale));
var pos = e.GetPosition(mNetworkUI);
mNetworkUI.Width = ZoomPanCanvas.ActualWidth / currrentScale;
mNetworkUI.Height = ZoomPanCanvas.ActualHeight /currrentScale;
var dummyTransform = new ScaleTransform(factor, factor, pos.X, pos.Y);
var offSet = new Point(dummyTransform.Value.OffsetX, dummyTransform.Value.OffsetY);
mNetworkUI.ViewModel.Network.SetTransformOffset(offSet);
}
And it follows the static helper function:
public static void RenderTransformAnimation(FrameworkElement element, Transform newTransform) {
MatrixAnimationUsingKeyFrames anim = new MatrixAnimationUsingKeyFrames();
var key1 = new DiscreteMatrixKeyFrame(element.RenderTransform.Value, KeyTime.FromPercent(0));
var key2 = new DiscreteMatrixKeyFrame(newTransform.Value, KeyTime.FromPercent(1));
Storyboard.SetTarget(anim, element.RenderTransform);
Storyboard.SetTargetProperty(anim, new PropertyPath(UIElement.RenderTransformProperty));
Storyboard sb = new Storyboard();
sb.Children.Add(anim);
sb.Duration = AnimationDuration;
sb.Begin();
}
It always throws an exception on the sb.Begin() call, telling me, something was not ok with my 'PropertyPath'. I don't know how to do it :(.
I mean, there is no way to directly create a "TransformAnimation", right? Only MatrixAnimations are available...
I've provided a simple animation of a ScaleTransform below. In the interests of providing a 'minimal' example, I only adjust the scale; I don't do any of the offset calculations that you're doing based on mouse position. You should be able to figure out where to go from here:
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
var factor = e.Delta > 0d ? 1.1d : 0.9d;
var t = mNetworkUI.RenderTransform as ScaleTransform;
if (t == null)
{
mNetworkUI.RenderTransform = t = new ScaleTransform(1d, 1d)
{
CenterX = 0.5d,
CenterY = 0.5d
};
}
var oldScale = (double)t.GetAnimationBaseValue(ScaleTransform.ScaleXProperty);
var newScale = oldScale * factor;
//
// Make sure `GetAnimationBaseValue()` reflects the `To` value next time
// (needed to calculate `oldScale`, and for the animation to infer `From`).
//
t.ScaleX = newScale;
t.ScaleY = newScale;
var animation = new DoubleAnimation
{
To = newScale,
Duration = TimeSpan.FromSeconds(0.5d),
DecelerationRatio = 0.5d,
FillBehavior = FillBehavior.Stop
};
//
// Use `HandoffBehavior.Compose` to transition more smoothly if an animation
// is already in progress.
//
t.BeginAnimation(
ScaleTransform.ScaleXProperty,
animation,
HandoffBehavior.Compose);
t.BeginAnimation(
ScaleTransform.ScaleYProperty,
animation,
HandoffBehavior.Compose);
}
I have the following code (Test only right now)
PlotPoint[] starLocations = new PlotPoint[4];
starLocations[0] = new PlotPoint(9,-2,1);
starLocations[1] = new PlotPoint(-3,6,1);
starLocations[2] = new PlotPoint(4,2,-3);
starLocations[3] = new PlotPoint(7,-8,9);
//draw the sector map
SectorMap ourMap = new SectorMap();
ourMap.reDraw(PlotPoint.getILLocs(starLocations));
SectorMap.cs
public void reDraw(float[,] givenLocs){
ILArray<float> ourPositions = givenLocs;
textBox1.Text = ourPositions.ToString();
var scene = new ILScene();
var plotCube = scene.Add(new ILPlotCube(false));
var ourPosBuffer = new ILPoints();
ourPosBuffer.Positions = ourPositions;
ourPosBuffer.Size = 3;
plotCube.Add(ourPosBuffer);
iLStarChart.Scene = scene;
}
Doing this, when I check the matrix at PlotPoint.getILLocs, I get a 4x3 matrix. When I check the passed matrix, it's again a 3x4
When I check ourPositions in SectorMap.cs, it has become a 3x4 matrix. Which is something I did not intend. What am I doing wrong?
I messed up, and I'm providing how here for other people's refrence:
1) It was, as Haymo Kutschbach said, a difference in storage scheme.
2) The confusion and lack of 3D grid was due to
var plotCube = scene.Add(new ILPlotCube(false));
instead of the
var plotCube = scene.Add(new IPlotCube(null,false));
I'm trying to create 1 complex composite shape on an InkCanvas, but I must be doing something wrong, as what I was expecting to happen, is not. I've tried several different incarnations of accomplishing this.
So I have this method.
private void InkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e)
{
Stroke stroke = e.Stroke;
// Close the "shape".
StylusPoint firstPoint = stroke.StylusPoints[0];
stroke.StylusPoints.Add(new StylusPoint() { X = firstPoint.X, Y = firstPoint.Y });
// Hide the drawn shape on the InkCanvas.
stroke.DrawingAttributes.Height = DrawingAttributes.MinHeight;
stroke.DrawingAttributes.Width = DrawingAttributes.MinWidth;
// Add to GeometryGroup. According to http://msdn.microsoft.com/en-us/library/system.windows.media.combinedgeometry.aspx
// a GeometryGroup should work better at Unions.
_revealShapes.Children.Add(stroke.GetGeometry());
Path p = new Path();
p.Stroke = Brushes.Green;
p.StrokeThickness = 1;
p.Fill = Brushes.Yellow;
p.Data = _revealShapes.GetOutlinedPathGeometry();
selectionInkCanvas.Children.Clear();
selectionInkCanvas.Children.Add(p);
}
But this is what I get:
http://img72.imageshack.us/img72/1286/actual.png
So where am I going wrong?
TIA,
Ed
The problem is that the Geometry returned by stroke.GetGeometry() is a path around the stroke, so the area you're filling with yellow is just the middle of the stroke. You can see this more clearly if you make the lines thicker:
_revealShapes.Children.Add(stroke.GetGeometry(new DrawingAttributes() { Width = 10, Height = 10 }));
You can do what you want if you convert the list of stylus points to a StreamGeometry yourself:
var geometry = new StreamGeometry();
using (var geometryContext = geometry.Open())
{
var lastPoint = stroke.StylusPoints.Last();
geometryContext.BeginFigure(new Point(lastPoint.X, lastPoint.Y), true, true);
foreach (var point in stroke.StylusPoints)
{
geometryContext.LineTo(new Point(point.X, point.Y), true, true);
}
}
geometry.Freeze();
_revealShapes.Children.Add(geometry);