【问题标题】:WPF InkCanvas access all pixels under the strokesWPF InkCanvas 访问笔划下的所有像素
【发布时间】:2015-05-02 01:05:13
【问题描述】:

看来WPF的InkCanvas只能提供笔画的点数(与笔画的宽高无关)。对于一个应用程序,我需要知道InkCanvas 绘制的所有点。

例如,假设笔划的宽度和高度为 16。使用这个笔划大小,我在InkCanvas 上画了一个点。有没有一种直接的方法来获取这个点中的所有 256 个像素(而不仅仅是这个巨大点的中心点)?

我为什么关心:
在我的应用程序中,用户使用 InkCanvas 在显示一些 3D 对象的 Viewport3D 上进行绘制。我想使用笔画的所有点来进行光线投射,并确定Viewport3D中的哪些对象被用户的笔画覆盖了。

【问题讨论】:

    标签: c# wpf inkcanvas viewport3d


    【解决方案1】:

    我发现了一种非常肮脏的处理方式。如果有人知道更好的方法,我将非常乐意投票并接受他们的回答作为答案。
    基本上我的方法包括获取每个笔划的Geometry,遍历该几何边界内的所有点并确定该点是否在几何内部。

    这是我现在使用的代码:

    foreach (var stroke in inkCanvas.Strokes)
    {
        List<Point> pointsInside = new List<Point>();
    
        Geometry sketchGeo = stroke.GetGeometry();
        Rect strokeBounds = sketchGeo.Bounds;
    
        for (int x = (int)strokeBounds.TopLeft.X; x < (int)strokeBounds.TopRight.X + 1; x++)
            for (int y = (int)strokeBounds.TopLeft.Y; y < (int)strokeBounds.BottomLeft.Y + 1; y++)
            {
                Point p = new Point(x, y);
    
                if (sketchGeo.FillContains(p))
                    pointsInside.Add(p);
            }
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用 StrokeCollection 的 HitTest 方法。我将您的解决方案的性能与此实现进行了比较,发现 HitTest 方法的性能更好。您的里程等。

      // get our position on our parent.
      var ul = TranslatePoint(new Point(0, 0), this.Parent as UIElement);
      
      // get our area rect
      var controlArea = new Rect(ul, new Point(ul.X + ActualWidth, ul.Y + ActualHeight));
                  
      // hit test for any strokes that have at least 5% of their length in our area
      var strokes = _formInkCanvas.Strokes.HitTest(controlArea, 5);
      
      if (strokes.Any())
      {
         // do something with this new knowledge
      }
      

      您可以在此处找到文档: https://docs.microsoft.com/en-us/dotnet/api/system.windows.ink.strokecollection.hittest?view=netframework-4.7.2

      此外,如果您只关心矩形中是否有任何点,您可以使用下面的代码。它比 StrokeCollection.HitTest 快一个数量级,因为它不关心笔画的百分比,因此它的工作量要少得多。

          private bool StrokeHitTest(Rect bounds, StrokeCollection strokes)
          {
              for (int ix = 0; ix < strokes.Count; ix++)
              {
                  var stroke = strokes[ix];
                  var stylusPoints = stroke.DrawingAttributes.FitToCurve ? 
                      stroke.GetBezierStylusPoints() : 
                      stroke.StylusPoints;
      
                  for (int i = 0; i < stylusPoints.Count; i++)
                  {
                      if (bounds.Contains((Point)stylusPoints[i]))
                      {
                          return true;
                      }
                  }
              }
              return false;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-23
        相关资源
        最近更新 更多