4 Replies Latest reply on Mar 16, 2012 3:12 AM by KevinSayer

    Bug in EditGeometry Class when moving polygons and polylines

    KevinSayer
      There seems to be a bug in the EditGeometry class and I thought I'd post my findings on here to see if anyone else has experienced this problem and whether there may be some kind of work around.

      The problem is that when moving a polygon or polyline, if you move it back over exactly the same position it was in when the edit started, it automatically cancels the edit. This happens because points in the original geometry are being updated. As Jennifer has pointed out in other threads, canceling the edit as a result of updating the original geometry is by design but the question is, why is the original geometry getting updated? This is happening inside the EditGeometry class and isn't related to my use of the class as it happens in simple, stripped down examples, including those that Jennifer has posted herself. (See the post dated 01-09-2012 04:17pm in this thread.) I'd suggest lining the vertices of the polygon up with the edge of the window before starting the move so that it's easier to return to the exact starting location.

      Below is the call stack from inside the GeometryEdited handler after the Cancel occurs:

      > EsriEditing.exe!EsriEditing.MainWindow.mEditGeometry_GeometryEdit(object sender, ESRI.ArcGIS.Client.EditGeometry.GeometryEditEventArgs e) Line 83 C#
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.OnGeometryEdit(ESRI.ArcGIS.Client.Graphic g, ESRI.ArcGIS.Client.Geometry.MapPoint newItem, ESRI.ArcGIS.Client.Geometry.MapPoint oldItem, ESRI.ArcGIS.Client.EditGeometry.Action action) + 0x5f bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.StopEdit(bool deletingVertex, bool cancelEdit) + 0x227 bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.CancelEdit() + 0x21 bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.OriginalGeometry_GeometryChanged(object sender, System.EventArgs e) + 0x63 bytes
      [Native to Managed Transition]
      [Managed to Native Transition]
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.Geometry.Geometry.raiseGeometryChanged() + 0x4f bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.Geometry.Polygon.coll_PointChanged(object sender, System.EventArgs e) + 0x4f bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.Geometry.PointCollection.raisePointChanged() + 0x57 bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.Geometry.PointCollection.point_GeometryChanged(object sender, System.EventArgs e) + 0x60 bytes
      [Native to Managed Transition]
      [Managed to Native Transition]
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.Geometry.Geometry.raiseGeometryChanged() + 0x4f bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.Geometry.MapPoint.Y.set(double value) + 0x53 bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.Offset(ESRI.ArcGIS.Client.Geometry.MapPoint p, double dx, double dy) + 0x69 bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.Offset(ESRI.ArcGIS.Client.Geometry.PointCollection pnts, double dx, double dy) + 0x7c bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.Offset(System.Collections.Generic.IEnumerable<ESRI.ArcGIS.Client.Geometry.PointCollection> pntsColl, double dx, double dy) + 0x7b bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.Offset(ESRI.ArcGIS.Client.Geometry.Geometry g, double dx, double dy) + 0x5c bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.HandleElementMove(System.Windows.Point screenPoint, ESRI.ArcGIS.Client.Geometry.MapPoint mapPoint) + 0x17e bytes
      ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.Map_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) + 0x10c bytes
      PresentationCore.dll!System.Windows.Input.MouseEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x34 bytes
      PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x27 bytes
      PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes
      PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0x1bf bytes
      PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes
      PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) + 0x35 bytes
      PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x311 bytes
      PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x42 bytes
      PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) + 0x62 bytes
      PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) + 0x2e2 bytes
      PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x22b bytes
      PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x75 bytes
      WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xbe bytes
      WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7a bytes
      WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, bool isSingleParameter) + 0x8a bytes
      WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x4a bytes
      WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x44 bytes
      WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, bool isSingleParameter) + 0x91 bytes
      WindowsBase.dll!System.Windows.Threading.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority priority, System.Delegate method, object arg) + 0x40 bytes
      WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0xdc bytes
      [Native to Managed Transition]
      [Managed to Native Transition]
      WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xc4 bytes
      WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
      WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes
      PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x1e bytes
      PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes
      PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes
      PresentationFramework.dll!System.Windows.Application.Run() + 0x19 bytes
      EsriEditing.exe!EsriEditing.App.Main() + 0x5e bytes C#
      [Native to Managed Transition]
      [Managed to Native Transition]
      mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x3a bytes
      Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes
      mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes
      mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes
      mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes

      Hopefully you will see this Jennifer and can either confirm the bug or explain the behaviour.

      Regards,
      Kevin
        • Re: Bug in EditGeometry Class when moving polygons and polylines
          JNery-esristaff
          It's seems impossible to move the graphic geometry back to its original location to cause a cancel. But based on the stack trace, the OriginalGeometry raised a GeometryChanged event that it was updated outside the EditGeometry. This may have been caused by changing the geometry in code (application): If you add/remove/update PointCollection or X/Y values. Or it may also be caused by existing bug that is triggered by cloning geometries. We have a fix for this in our next release.
          • Re: Bug in EditGeometry Class when moving polygons and polylines
            KevinSayer
            Hi Jennifer,

            Thanks for your reply.  I forgot to mention versions, so to clarify, we're currently using version 2.4, although this problem also existed in version 2.3.  I guess when you say that it might be fixed in the next version, you're referring to version 3.0?  Do you have any idea when that might be released?

            Just out of interest, attached (at the bottom) is a zip file containing a small VS2010 project  for a really simple application that puts a square on the map and doesn't even bother attaching to the geometry changed handler.  As you can see, there's absolutely no application code fiddling with the original geometry.

            The best repro is to run this and then pan the map so that the square is lined up with the edges of the button and window as show in the screen shot below.

            [ATTACH=CONFIG]12716[/ATTACH]

            Now press the button and move the two vertices of the square so it looks like the following screen shot.

            [ATTACH=CONFIG]12717[/ATTACH]

            Now move the shape away from the corner and then slowly back again so that the top left corner is exactly where it started.  You might have to hover around the corner a little before you get it in exactly the same place.  You'll know when you do however as the shape suddenly reverts back to a square and it comes out of edit mode. This is all obviously due to the edit being cancelled becaue it thinks you've changed the original geometry.

            Hopefully this is indeed the same bug that you mentioned will be fixed in the next release.

            This leads me on to another, possibly related issue however:

            There appears to be a bug in the EditGeometry class which causes a NullReferenceException and crashes our application.  This is obviously a little more serious from our perspective, and is also reproducible from the same application as above.

            The crash happens whilst in edit mode and moving a vertex over another existing vertex.  You might have to be quite patient to reproduce this in this little application as just grabbing a vertex and waving it over another will not suffice.  You need to hover over another vertex and keep slowly moving the mouse around.  Even then it might take some time before it happens.  This might sound a little contrived but the fact is, it happens much more readily in our main application in which just dragging a point reasonably quickly across another will usually suffice.  This leads me to suspect that it's probably thread related and more possibly down to garbage collection and the use of weak references in the drawing code. The call stack at the end of this post results from this when breaking on first chance exceptions.  Hopefully this might give some indication as to what is going on.

            If you can't get it to occur, a slightly more involved but possible more consistent repro is:

            1> Edit the square and drag one of the corners into the centre so that it looks like the following.
            [ATTACH=CONFIG]12718[/ATTACH]

            2> Add a new vertex so it looks like the following and then come out of edit mode by clicking on the shape.
            [ATTACH=CONFIG]12719[/ATTACH]

            3> Enter edit mode again and drag the new vertex added in step 2 slowly over the corner that you dragged to the centre in step 1.
            4> Continue hovering over the other vertex, slowly moving the mouse around and the exception will ususall occur within a couple of seconds.

            Again, this might sound quite contrived but in our application it generally happens much easier than this.  Below is the stack trace when this exception is raised. Hope this is enough information and you have time to take a look at this.

            Regards,
            Kevin


            > ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.UpdateVertexPosition(ESRI.ArcGIS.Client.Geometry.MapPoint pnt, bool isTransformPoint) + 0x838 bytes
              ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.HandleElementMove(System.Windows.Point screenPoint, ESRI.ArcGIS.Client.Geometry.MapPoint mapPoint) + 0x29a bytes
              ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.EditGeometry.Map_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) + 0x10c bytes
              PresentationCore.dll!System.Windows.Input.MouseEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x34 bytes
              PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x27 bytes
              PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes
              PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0x1bf bytes
              PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes
              PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) + 0x35 bytes
              PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x311 bytes
              PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x42 bytes
              PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) + 0x62 bytes
              PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) + 0x2e2 bytes
              PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x22b bytes
              PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x75 bytes
              WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xbe bytes
              WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7a bytes
              WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, bool isSingleParameter) + 0x8a bytes
              WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x4a bytes
              WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x44 bytes
              WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, bool isSingleParameter) + 0x91 bytes
              WindowsBase.dll!System.Windows.Threading.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority priority, System.Delegate method, object arg) + 0x40 bytes
              WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0xdc bytes
              [Native to Managed Transition]
              [Managed to Native Transition]
              WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xc4 bytes
              WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
              WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes
              PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x1e bytes
              PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes
              PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes
              PresentationFramework.dll!System.Windows.Application.Run() + 0x19 bytes
              EsriEditing.exe!EsriEditing.App.Main() + 0x5e bytes C#
              [Native to Managed Transition]
              [Managed to Native Transition]
              mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x3a bytes
              Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes
              mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes
              mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes
              mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes
            • Re: Bug in EditGeometry Class when moving polygons and polylines
              shweekia
              Hi Kevin,
              I have the same NullReferenceException problem as you as you would have read from my post. I would like to share with you what I did.
              The following codes will help to catch the exception and not let the application crash. But of course the root of the problem still lies with the dll itself which only ESRI can solve. Heres what I did:

              In App.xaml, the registration of the event handler is initialized
              <Application x:Class="UnhandledExceptionHandler.App"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  StartupUri="Window1.xaml"
                  Startup="Application_Startup"
                 DispatcherUnhandledException="Application_DispatcherUnhandledException">
                  <Application.Resources>
                      
                  </Application.Resources>
              </Application>


              A method is added to App.xaml.cs which will handle this event. This is where the exception handling logic will be added.

                private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
                      {
                           
                             //do whatever handling you want here

                              //must set e.handled = true so that application can resume execution
                              e.Handled = true;
                         
                      }

              Hopefully this works for you (temporary solution until v3 comes along) So far my users have not complained yet. Thanks
              • Re: Bug in EditGeometry Class when moving polygons and polylines
                KevinSayer
                Hi shweekia,

                I appreciate the response and thanks for the suggestion.  Unfortunately it's not quite that simple for us as we are writing a COM plugin for our company's flagship MFC application.   The plugin is written in c# and uses interop to communicate with the main application.  It is effectively a modeless window that hosts the WPF map control inside an ElementHost. The main application team (which I've worked on for many years in the past) would definitely not be happy adding a "catch all" top level exception handler.  It would also require a new release of the flagship product which is obviously not going to happen just to work around a bug in third party code.  If Esri haven't resolved the problem before we release the next version of the plugin, the most likely solution will be that we have to drop the shape editing functionality.  This would be a real shame given the context in which we use it.

                Regards,
                Kevin