GMapRoute OnClick event; Alternative routes

Topics: Feature Requests
Dec 25, 2011 at 11:50 PM

Hi!

Thanks for this cool app)

As I can see it's not possible to handle click event on a route, is it? Or I missed it?

And the second: it would be a good feature if you use alternatives parameter (like it is in google maps api) in a route request for ability to choose a route that user prefer.

Coordinator
Jan 9, 2012 at 10:56 AM

yes, WindowsForms version doesn't have this event

alternatives option would be nice

Feb 14, 2012 at 1:08 PM

radioman, is there any chance you could add the OnClick, OnEnter and OnLeave events to routes along with the alternatives parameter?

Please, please, please :)

Thanks

Charlotte

Coordinator
Feb 14, 2012 at 1:18 PM

tell me how and i'll do it in the instant ;}

Feb 15, 2012 at 10:13 AM

Not sure radioman, but I figured it must be problematic otherwise you would have already implemented something on the routes - I'm assuming the issue is that the routes are so thin (in terms of pixels) that it is difficult to capture the events [is my assumption correct or is it something else]...

If my assumption is correct on the issue, how about the following to solve the issue...

If there was an internally used buffer area of x pixels (user defined on creating) around the route that was not visible but only used for the purpose of the OnClick, OnEnter and OnLeave events, it would be possible to then click on the route to select it to give the user the ability to delete it or adjust the vertices on it the way we can on polygons. It's almost like the route needs it's own internal polygon property which is not visible to the user but is used for this buffer area. Then, if the mouse pointer is over this hidden polygon, the 3 events work in the same way the normal polygon does. On defining the route, if a buffer size of 0 was specified, no internal polygon object would be created thus the route is not selectable. Does this make sense? Sounds good in theory perhaps but may not be easy to implement in reality and obviously your bloating things a bit if you have a lot of routes on the screen but I could live with that...

Regards the alternatives keyword - any chance of doing something with it?

Thanks and kind regards

Charlotte

Coordinator
Feb 15, 2012 at 10:50 AM

so far no one did anything on that ;}

Feb 16, 2012 at 3:03 PM
Edited Feb 16, 2012 at 3:06 PM

I did :-) But in a slightly different way, I needed to display different colored "Offset bars" along a given route (road, the colors symbolize a condition for this road, e.g. pot holes,...). Check out this screenshot:

 

Offsetbars

 

I did it, by storing the GraphicsPath of each part of an OffsetBar, and then checking if x,y is inside using GraphicsPath.IsVisible(x,y) method (similar, as radioman did it with the markers). Check out this code snippet in a class that derives from GMapControl.cs:

 

        /// <summary>
        /// Handle mouse move event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Map_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //Check if the mouse is over a GraphicsPath of an Offset bar
            if (!this.IsDragging && this.ShowOffsetBars)
            {
                bool mouseover = false;

                foreach (var o in this.Overlays)
                {
                    if (o != null && o.IsVisibile)
                    {
                        foreach (GMapRoute r in o.Routes)
                        {
                            if (r.IsVisible && (r is GMapRouteEnhanced))
                            {
                                GMapRouteEnhanced re = (GMapRouteEnhanced)r;
                                foreach (var ob in re.OffsetBars)
                                {
                                    foreach (var part in ob.Parts)
                                    {
                                        if (part.IsHitTestVisible)
                                        {
                                            GraphicsPath gp = part.Path;
                                            if (gp.IsVisible(e.X, e.Y))
                                            {
                                                IsMouseOverOffsetBarPart = true;
                                                mouseover = true;

                                                if (!part.IsMouseOver)
                                                {
                                                    this.Cursor = Cursors.Hand;
                                                    part.IsMouseOver = true;
                                                    if (OnOffsetBarPartEnter != null)
                                                    {
                                                        OnOffsetBarPartEnter(ob, part);
                                                    }
                                                }
                                            }
                                            else if (part.IsMouseOver)
                                            {
                                                if (!mouseover)
                                                    this.Cursor = Cursors.Default;
                                                part.IsMouseOver = false;
                                                if (OnOffsetBarPartLeave != null)
                                                {
                                                    OnOffsetBarPartLeave(ob, part);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                IsMouseOverOffsetBarPart = mouseover;
            }          
        }

 

So you get the idea, it's just as easy to create a new GMapRoute enhanced class, and store the graphics path of the route (if you want, with a Pen with a greater Width, so you don't have to hit it exactly with the mouse). P.S.: I got the idea with the GraphicsPath from a fork created by Knightlie.

Coordinator
Feb 16, 2012 at 3:22 PM

thanks for reminder, i'll try to add this tip for routes by default

Feb 16, 2012 at 6:21 PM
Edited Feb 16, 2012 at 6:21 PM

Thanks Xandolph - that screen shot looks awesome. Any chance you could share the code the for the legend \ scale bar?

Regards

Charlotte

Feb 16, 2012 at 10:19 PM
Edited Feb 16, 2012 at 10:19 PM

Here you go: (override OnPaintOverlays in GMapControl):

 

 

#region Scale variables

        /// <summary>
        /// The font for the m/km markers
        /// </summary>
        private Font fontCustomScale = new Font("Arial", 6);

        /// <summary>
        /// The font for the scale header 
        /// </summary>
        private Font fontCustomScaleBold = new Font("Arial", 10, FontStyle.Bold);

        /// <summary>
        /// The brush for the scale's background
        /// </summary>
        private Brush brushCustomScaleBackColor = new SolidBrush(Color.FromArgb(200, 185, 215, 255));

        /// <summary>
        /// The Textcolor for the scale's fonts
        /// </summary>
        private Color colorCustomScaleText = Color.FromArgb(20, 65, 140);

        /// <summary>
        /// The width of the scale-rectangle
        /// </summary>
        private int intScaleRectWidth = 300;

        /// <summary>
        /// The height of the scale-rectangle
        /// </summary>
        private int intScaleRectHeight = 50;

        /// <summary>
        /// The height of the scale bar
        /// </summary>
        private int intScaleBarHeight = 10;

        /// <summary>
        /// The padding of the scale
        /// </summary>
        private int intScaleLeftPadding = 10;

#endregion

 

 

        /// <summary>
        /// Draw extra stuff here (E.g. a legend for the map)
        /// </summary>
        /// <param name="drawingContext"></param>
        protected override void OnPaintOverlays(System.Drawing.Graphics g)
        {
            base.OnPaintOverlays(g);

            g.SmoothingMode = SmoothingMode.HighQuality;
            if (ShowCustomScale)
            {
                double resolution = this.MapProvider.Projection.GetGroundResolution((int)this.Zoom, Position.Lat);

                int px10 = (int)(10.0 / resolution);            // 10 meters
                int px100 = (int)(100.0 / resolution);          // 100 meters
                int px1000 = (int)(1000.0 / resolution);        // 1km   
                int px10000 = (int)(10000.0 / resolution);      // 10km  
                int px100000 = (int)(100000.0 / resolution);    // 100km  
                int px1000000 = (int)(1000000.0 / resolution);  // 1000km
                int px5000000 = (int)(5000000.0 / resolution);  // 5000km

                //Check how much width we have and set the scale accordingly
                int availableWidth = (intScaleRectWidth - 2 * intScaleLeftPadding);

                //5000 kilometers:
                if (availableWidth >= px5000000)
                    DrawScale(g, px5000000, availableWidth, 5000, "km");
                //1000 kilometers:
                else if (availableWidth >= px1000000)
                    DrawScale(g, px1000000, availableWidth, 1000, "km");
                //100 kilometers:
                else if (availableWidth >= px100000)
                    DrawScale(g, px100000, availableWidth, 100, "km");
                //10 kilometers:
                else if (availableWidth >= px10000)
                    DrawScale(g, px10000, availableWidth, 10, "km");
                //1 kilometers:
                else if (availableWidth >= px1000)
                    DrawScale(g, px1000, availableWidth, 1, "km");
                //100 meters:
                else if (availableWidth >= px100)
                    DrawScale(g, px100, availableWidth, 100, "m");
                //10 meters:
                else if (availableWidth >= px10)
                    DrawScale(g, px10, availableWidth, 10, "m");
            }
        }

        /// <summary>
        /// Draw the scale
        /// </summary>
        /// <param name="g"></param>
        /// <param name="resLength"></param>
        /// <param name="availableWidth"></param>
        /// <param name="totalDimenson"></param>
        /// <param name="unit"></param>
        private void DrawScale(System.Drawing.Graphics g, int resLength, int availableWidth, int totalDimenson, String unit)
        {
            Point p = new System.Drawing.Point(this.Width - (intScaleRectWidth + 10), this.Height - (intScaleRectHeight + 10));
            Rectangle rect = new Rectangle(p, new Size(intScaleRectWidth, intScaleRectHeight));
            g.FillRectangle(brushCustomScaleBackColor, rect);
            Pen pen = new Pen(colorCustomScaleText, 1);
            g.DrawRectangle(pen, rect);
            SizeF stringSize = new SizeF();
            Point pos = new Point();

            //Header:
            String scaleString = "Maßstab";
            stringSize = g.MeasureString(scaleString, fontCustomScaleBold);
            pos = new Point(p.X + (rect.Width - (int)stringSize.Width) / 2, p.Y + 3);
            g.DrawString(scaleString, fontCustomScaleBold, pen.Brush, pos);

            pos = new Point(p.X + intScaleLeftPadding, pos.Y + 30);

            //How many rectangles fit?
            int numRects = availableWidth / resLength;
            Size rectSize = new Size(resLength, intScaleBarHeight);
            //Center rectangle
            pos.X += (availableWidth - resLength * numRects) / 2;
            //Draw rectangles:
            for (int i = 0; i < numRects; i++)
            {
                Rectangle r = new Rectangle(pos, rectSize);
                if (i % 2 == 0)
                    g.FillRectangle(pen.Brush, r);
                else
                    g.DrawRectangle(pen, r);
                //Draw little vertical lines
                g.DrawLine(pen, pos, new Point(pos.X, pos.Y - 5));
                //Draw labels:
                int dist = i * totalDimenson;
                stringSize = g.MeasureString(dist + " " + unit, fontCustomScale);
                g.DrawString(dist + " " + unit, fontCustomScale, pen.Brush, new Point(pos.X - (int)stringSize.Width / 2, pos.Y - (7 + (int)stringSize.Height)));
                //Finally set new point
                pos = new Point(pos.X + resLength, pos.Y);
            }
            //Draw last line:
            g.DrawLine(pen, pos, new Point(pos.X, pos.Y - 5));
            //Draw last label
            int m = numRects * totalDimenson;
            stringSize = g.MeasureString(m + " " + unit, fontCustomScale);
            g.DrawString(m + " " + unit, fontCustomScale, pen.Brush, new Point(pos.X - (int)stringSize.Width / 2, pos.Y - (7 + (int)stringSize.Height)));
        }

 

Coordinator
Feb 17, 2012 at 9:42 AM

status: events added

Feb 17, 2012 at 11:31 AM

Thanks Xandolph :-)

Feb 17, 2012 at 2:02 PM

Thanks radioman for these events :-)