0

I am creating a small app that uses a MapWinGIS control and allows a polygon layer to be edited. Users can add/delete/edit polygons. All is working fine, but the operation to finish a new polygon (Ctrl + Left Mouse Button) is not from intuitive. We would like to implement this functionality by using the more intuitive "left click on the first vertex" which most drawing & geospatial packages use.

How can I do this? I should be able to trap the left mouse event, but need to compare the coord with the start (which is stored where?) and then initiate the "finish this polygon" operation. I see the StartEdit() operation in the ShapeEditor documentation, but no equivalent FinishEdit()!?

  • I suppose you should edit the source code of mapwingis.codeplex.com/SourceControl/latest#src/Editor/… and make "ctrl" to listen to something else. I wouldn't say that "most drawing & geospatial packages use left click on the first vertex" but there are many different ways. Which software do you mean? – user30184 Feb 27 '16 at 15:35
  • Editing the source could lead to a maintenance nightmare in the future. – winwaed Feb 27 '16 at 20:54
  • MapWinGis is an open source project. Make a patch and if it will be accepted to the code base there will be no nightmare at all with maintenance. You can also write to MapWinGis forum and make a feature request. Maybe somebody feels your suggestion good enough and makes the change. – user30184 Feb 27 '16 at 21:14
0

I was not able to trap the left mouse button because the ShapeEditor is trapping all left mouse buttons. That handler could be replaced, but then I would end up rewriting the ShapeEditor.

The solution was to trap the right mouse button. So the user right-mouse clicks the last vertex to add that vertex and close the shape.

The mouse click is trapped as follows:

    axMap1.MouseDownEvent += axMap1_MouseDown;
    axMap1.SendMouseDown = true;

The ShapeEditor allows existing vertices to be modified, but it does not allow new vertices to be added to the shape. Therefore it has to be saved, then the resulting shape modified.

Here is the handler's implementation:

private void axMap1_MouseDown(object sender, AxMapWinGIS._DMapEvents_MouseDownEvent e)
{
    // only trap the right button (2)
    // button 1 is already trapped by MapWinGIS
    if (e.button != 2)
        return;


    if (axMap1.CursorMode == tkCursorMode.cmAddShape)
    {   // adding a shape that needs finishing off?
        if (se.numPoints >= 2)
        {
            ShapeEditor se = axMap1.ShapeEditor;
            Shapefile sf = axMap1.get_Shapefile(_lyPolygon);

            // find the mouse point => final point for the shape
            MapWinGIS.Point pnt = new MapWinGIS.Point();
            double x = 0.0;
            double y = 0.0;
            axMap1.PixelToProj(e.x, e.y, ref x, ref y);
            pnt.x = x;
            pnt.y = y;

            // find the points at the beginning and end of the shape - we need to insert the point between these
            double aX, aY, bX, bY;
            se.get_PointXY(0, out aX, out aY);
            se.get_PointXY(se.numPoints-1, out bX, out bY);

            axMap1.ShapeEditor.SaveChanges();

            Shape shp = sf.get_Shape(sf.NumShapes-1); 
            int index=0;
            double x1=0, y1=0, x2=0, y2=0;
            for (int idx = 0; idx < shp.numPoints; idx++ )
            {
                shp.get_XY(idx, ref x1, ref y1);
                if (CompareDouble(x1,aX)  && CompareDouble(y1,aY))
                {   // found one of the points - try either side
                    int idx2 = (idx + 1) % shp.numPoints;
                    shp.get_XY(idx2, ref x2, ref y2);
                    if (CompareDouble(x2,bX)  && CompareDouble(y2,bY))
                    {   // found the other
                        index = idx2; // use the higher index
                        break; 
                    }
                    idx2 = (idx - 1 + shp.numPoints) % shp.numPoints;
                    shp.get_XY(idx2, ref x2, ref y2);
                    if (CompareDouble(x2, bX) && CompareDouble(y2, bY))
                    {   // found the other
                        index = idx; // use the higher index
                        break;
                    }

                }
            }
            shp.InsertPoint(pnt, ref index);                   
            axMap1.Redraw();
        }
        else
        {   // not enough vertices => clear
            axMap1.ShapeEditor.Clear();
        }
    }
 }


    /// <summary>
    /// True if a is within *EPSILON of b
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    private bool CompareDouble(double a, double b)
    {
        // check close to zero first
        if ( Math.Abs(a) < (EPSILON-1.0)   &&  Math.Abs(b) < (EPSILON-1.0) )
            return true;
        if (a==b)
            return true; // handles infinity

        if (a < 0.0)
        {   // at least one is negative - assume both are
            if (a * EPSILON > b)
                return false;
            if (b * EPSILON > a)
                return false;
        }
        else // at least one is positive
        {
            if (a * EPSILON < b)
                return false;
            if (b * EPSILON < a)
                return false;
            return true;
        }
        return false; // should not reach here
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.