Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help Wanted: Testing the Hit-Test feature #148

Open
paulushub opened this issue Aug 29, 2020 · 17 comments
Open

Help Wanted: Testing the Hit-Test feature #148

paulushub opened this issue Aug 29, 2020 · 17 comments

Comments

@paulushub
Copy link
Contributor

paulushub commented Aug 29, 2020

With the updates (d0e6dc2), the current hit testing issue with transformed geometry is fixed.
However, more tests are needed to verify this feature and your help is needed.

The hit test feature is implemented in the WpfDrawingDocument class and will be the basis of interactivity support in the controls; SvgCanvas and SvgViewbox.
A sample application WpfTestSvgControl is available for testing this important feature.

How to help?

  1. Get the current source from the repository and build it.
  2. Run the sample application, WpfTestSvgControl and use it to open SVG files.
  3. Perform the hit tests in the drawing panel and observe the results in the bottom panel.
  4. Report any issue and suggestions for improvements.
  5. Try some of the options in the Settings tab, but keep the Include support for SharpVectors Runtime library option checked.

shots

@paulushub paulushub self-assigned this Aug 29, 2020
@paulushub paulushub pinned this issue Aug 29, 2020
@paulushub paulushub changed the title Help Needed: Testing the Hit-Test feature Help Wanted: Testing the Hit-Test feature Aug 29, 2020
@ThunderChild-001
Copy link

ThunderChild-001 commented Nov 3, 2020

I am currently playing around with this feature. Unfortunately I'm having a little difficulty getting it to work with the SVGs that I have been given.

The paths and rectangles in this document are grouped into a layer which has a transform. This seems to be causing the bounds check to fail in HitTestDrawing() in WpfDrawingDocument.cs. He comes to the line: if (group.Bounds.Contains(pt)) and leaves.
I think its something to do with him looking in the wrong location due to the transform?

There maybe also a problem with transparent objects. I need to investigate further as far as this goes but he doesn't seem to like some of the styles that are used. I will also keep digging but im not sure if I will discover the problem.

I'm attaching one of the SVGs incase it is something of interest.

arme_aussen.zip

``

@paulushub
Copy link
Contributor Author

@KarlAbson Thanks for the feedback, I will investigate with the attached file to improve this feature.

@ThunderChild-001
Copy link

@paulushub I had some success in fixing this. It appears that there are two problems.
The first is the transformation / grouping node and the second is the 50% transparency of the objects.
When both were removed the objects become selectable and are found.

The first problem can be easily fixed by not using the transform. The second of the transparency is not so easy. It would be nice to be able to use this. Do you have an idea as to why transparency would cause a problem?

Many thanks,
Karl

@paulushub
Copy link
Contributor Author

@KarlAbson Thanks for the updates. I cannot tell why the transparency will have effect, I will look into it. The transformation and maybe clipping are the main problems I thought I needed to resolve to this to work well. The WPF documentation does not help with this "low-level" issues and I have not found any sample addressing this issue.

@ThunderChild-001
Copy link

@paulushub I found a solution for the transparency issue.

In HitTestDrawing(DrawingGroup group, Point pt, out Drawing hitDrawing) in WpfDrawingDocument.cs,
Instead of using "SvgObject.GetId(drawing)" I use "SvgObject.GetId(group)".

I'm not sure if it's being put into a group with another node due to the transparency.
This solution also works for SvgObject.GetUniqueId()

As far as the other problem goes, I simply won't use the transformations / groupings.
I simply removed them and it works fine.

@paulushub
Copy link
Contributor Author

@KarlAbson By my tests, the hit-test for your drawing is working as expected!
The issue here is, you have semi-transparent rectangle drawings in front of the main drawings are these are rightly getting hit.
If you have the control over the source of the drawings, then you can separate the main drawings and the semi-transparent rectangles into different layers. Then we can provide options to specify the hit-test target layer, where needed.

Or if you can come with some other options, I will look into it.

@ThunderChild-001
Copy link

@paulushub Thanks for looking into this. Yes I also worked this out after further investigation. As I mentioned in my comment on Friday, the hit test works. He finds the hit object but it's the calls to SvgObject.GetUniqueId() / SvgObject.GetId(drawing) that needed changing. When you click on the slightly transparent objects you need to pass the group rather than the drawing. If you pass the drawing these methods return null when transparency is used.

@paulushub
Copy link
Contributor Author

@KarlAbson Trying to create a new Nuget package today, I will get back to this issue.

@ThunderChild-001
Copy link

Hallo there,

I finally found time to come back to this. I'm attaching a modified version of WpfDrawingDocument.cs which solves the problems. I'm not an expert however with this code so I hope that this does not cause any other problems.

The method WpfDrawingDocument.HitTest(Point) originally returned IsHit as false and SelectedItem as null with the test SVG that we have. I believe that this is due to the groups and the particular styles used. With the following changes this is resolved.

Here is a quick overview of the changes made:

  • Line 428 - call to HitTestDrawing(groupDrawing, ptDisplay, out foundDrawing, out _hitGroup) now has an extra out parameter, _hitGroup.
    This is basically the first parameter groupDrawing. For some reason GroupDrawing changes during the execusion of this method meaning that it can be used to get a unique ID if it is returned. No idea why it changes, I did not have that much time to investigate but to my knowledge this method only uses the parameter and does not change it...something else must be happening to it during the methods execution. If the original groupDrawing is used before or after the method a unique ID is not found.

  • Line 387 - private Tuple<DrawingGroup.Drawing> PerformHitTest(Point pt) now returns a tuple.
    Here we return both the hit DrawingGroup and the Drawing so that it can be used in the calling method. Originally only the Drawing was returned but since this does not give a uniqueID I also pass the DrawingGroup back.

  • Line 332 - public WpfHitTestResult HitTest(Point point)
    In this method Item2 of the tuple (Drawing) is used in a call to GetUniqueId. This is as before.
    If this returns white space the same call is used with Item1 (DrawingGroup). This results in the uniqueId being found.

Now the HitTest method returns the WpfHitTestResult with the selectedElement and IsHit as true where as before they were null and false respectively.

[WpfDrawingDocument.zip](https://github.com/ElinamLLC/SharpVectors/files/5607932/WpfDrawingDocument.zip)

@paulushub
Copy link
Contributor Author

@KarlAbson Thanks for the updates. The hit-test code has evolved a bit, which makes it different from yours. I am trying to see how to incorporate your codes, but I could not get it working with the image file you posted.
Are you using a modified version of your image file? Your updated codes will not hit anything on the current image.

@ThunderChild-001
Copy link

@paulushub True! I forgot that I also altered the SVG in illustrator to remove the main grouping.
Here is a new updated file.
arme_aussen.zip

@amine-aboufirass
Copy link

@paulushub How do we build the solution? I keep getting the following error:

MSB3030: Could not copy the file "WebView2Loader.dll" because it was not found.

@paulushub
Copy link
Contributor Author

@amine-aboufirass I will check and get back to you - for sometime now, I have not tested this sample.

@paulushub
Copy link
Contributor Author

@amine-aboufirass Are you trying the WpfTestOtherSvg sample?
It seems it is the only sample using the WebViews.Core for the Edge Browser. Please avoid this sample,
it is for comparing results with different browsers and other SVG implements etc. Not really meant for others.,

The sample for this thread is name WpfTestSvgControl

@justinci
Copy link

(https://stackoverflow.com/questions/78045278/wpfdrawingdocument-hittest-with-rectangle-always-return-null)

I tried var histTest = _drawingDocument.HitTest(new Rect(x, y, width, height), IntersectionDetail.Intersects); , but elements are always null.

@paulushub
Copy link
Contributor Author

Please provide more information.
new Rect(x, y, width, height) does not mean much unless you explain how you created it, relative to the SVG image.

@justinci
Copy link

justinci commented Mar 1, 2024

Hi @paulushub ,

I am using Drawing Page to load the SVG , I have written a code to draw a rectangle inside the Drawing Page

#region Rectangle Draw

  private void canDraw_MouseDown(object sender, MouseButtonEventArgs e)
  {
      StartPoint = Mouse.GetPosition(svgViewer);
      LastPoint = StartPoint;
      DragRectangle = new System.Windows.Shapes.Rectangle();
      DragRectangle.Width = 1;
      DragRectangle.Height = 1;
      DragRectangle.Stroke = System.Windows.Media.Brushes.Red;
      DragRectangle.StrokeThickness = 1;
      DragRectangle.Cursor = Cursors.Cross;

      svgViewer.Children.Add(DragRectangle);
      Canvas.SetLeft(DragRectangle, StartPoint.X);
      Canvas.SetTop(DragRectangle, StartPoint.Y);

      svgViewer.MouseMove += canDraw_MouseMove;
      svgViewer.MouseUp += canDraw_MouseUp;
      svgViewer.CaptureMouse();
  }

  private void canDraw_MouseMove(object sender, MouseEventArgs e)
  {
      LastPoint = Mouse.GetPosition(svgViewer);
      DragRectangle.Width = Math.Abs(LastPoint.X - StartPoint.X);
      DragRectangle.Height = Math.Abs(LastPoint.Y - StartPoint.Y);
      Canvas.SetLeft(DragRectangle, Math.Min(LastPoint.X, StartPoint.X));
      Canvas.SetTop(DragRectangle, Math.Min(LastPoint.Y, StartPoint.Y));
  }

  private void canDraw_MouseUp(object sender, MouseButtonEventArgs e)
  {
      svgViewer.ReleaseMouseCapture();
      svgViewer.MouseMove -= canDraw_MouseMove;
      svgViewer.MouseUp -= canDraw_MouseUp;
      svgViewer.Children.Remove(DragRectangle);

      if (LastPoint.X < 0) LastPoint.X = 0;
      if (LastPoint.X >= svgViewer.ActualWidth) LastPoint.X = svgViewer.ActualWidth - 1;
      if (LastPoint.Y < 0) LastPoint.Y = 0;
      if (LastPoint.Y >= svgViewer.ActualHeight) LastPoint.Y = svgViewer.ActualHeight - 1;

      int x = (int)Math.Min(LastPoint.X, StartPoint.X);
      int y = (int)Math.Min(LastPoint.Y, StartPoint.Y);
      int width = (int)Math.Abs(LastPoint.X - StartPoint.X) + 1;
      int height = (int)Math.Abs(LastPoint.Y - StartPoint.Y) + 1;



      RectangleGeometry rectangleGeometry = new RectangleGeometry(new Rect(x + svgViewer.DisplayOffset.X, y + svgViewer.DisplayOffset.Y, width, height));


      // Clear the previous visualization
      if (_drawingVisual != null)
      {
          svgViewer.HostVisual.Children.Remove(_drawingVisual);
          _drawingVisual = null;
      }


      // Create a new visual for the selected element
      _drawingVisual = new System.Windows.Media.DrawingVisual();
      DrawingContext drawingContext = _drawingVisual.RenderOpen();

      // Draw a bounding box around the selected element
      var boundsDrawing = new GeometryDrawing(null,
           new Pen(Brushes.DarkRed, 2), rectangleGeometry);

      // Push transformations to apply zoom
      drawingContext.PushTransform((Transform)svgViewer.DisplayTransform.Inverse);

      // Draw the bounding box
      drawingContext.DrawDrawing(boundsDrawing);

      drawingContext.Pop();
      drawingContext.Close();

      // Add the new visual to the host visual
      svgViewer.HostVisual.Children.Add(_drawingVisual);

      **var histTest= _drawingDocument.HitTest(new Rect(x,y,width,height),IntersectionDetail.Intersects);**

     
  }

     #endregion

But unfortunately I was not able to get the elements using the _drawingDocument.HitTest() method

Regards
Jestin CI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants