【问题标题】:Get List<Segment> from a PathGeometry从 PathGeometry 获取 List<Segment>
【发布时间】:2018-07-19 15:10:25
【问题描述】:

我在画布上画了几个形状。我有两种形状:椭圆和路径。

现在,当我在画布上单击时,我想获得最近的形状。

我可以为 Ellipse 做点什么,但对于 Path,我不知道如何获取它的坐标。

这是我用来生成列表的代码,以防该方法中的某些内容不是最佳的:

具体来说,“percage”是钻孔,如果Type=12,则表示我画了一个槽(路径)。否则我画一个圆(椭圆)

if (percage.Type == 12)
{
    double r = percage.Diametre / 2;
    LineSegment ligne1 = new LineSegment();
    LineSegment ligne2 = new LineSegment();
    Point ptCentre = new Point(dx + percage.Coor_X, this.MyScrollViewer.ActualHeight * echelle - dy - percage.Coor_Y);
    double angle = percage.AnglePer;
    double xLeft = ptCentre.X - r;
    double xRight = ptCentre.X + r;
    double yUp = ptCentre.Y - ((percage.Longueur / 2) - r);
    double yDown = ptCentre.Y + ((percage.Longueur / 2) - r);
    Point pt1 = new Point(xLeft, yUp);
    Point pt2 = new Point(xRight, yUp);
    Point pt3 = new Point(xRight, yDown);
    Point pt4 = new Point(xLeft, yDown);
    pt1 = Global.RotatePoint(pt1, ptCentre, angle - 90);
    pt2 = Global.RotatePoint(pt2, ptCentre, angle - 90);
    pt3 = Global.RotatePoint(pt3, ptCentre, angle - 90);
    pt4 = Global.RotatePoint(pt4, ptCentre, angle - 90);

    Path arc_path1 = new Path();
    arc_path1.Stroke = Brushes.Red;
    arc_path1.StrokeThickness = 2;
    PathGeometry pathGeometry = new PathGeometry();
    ArcSegment arc1 = new ArcSegment();
    ArcSegment arc2 = new ArcSegment();
    PathFigure pathfigure1 = new PathFigure();
    PathFigure pathfigure2 = new PathFigure();
    arc1.Point = new Point(pt2.X, pt2.Y);
    arc1.Point = new Point(pt4.X, pt4.Y);
    pathfigure1.StartPoint = new Point(pt1.X, pt1.Y);
    pathfigure1.StartPoint = new Point(pt3.X, pt3.Y);
    SweepDirection sd = SweepDirection.Counterclockwise;
    if (yUp < yDown)
    {
        sd = SweepDirection.Clockwise;
    }
    arc1.Size = new Size(r, r);
    arc1.SweepDirection = sd;
    arc2.Size = new Size(r, r);
    arc2.SweepDirection = sd;
    arc1.Point = pt2;
    arc2.Point = pt4;
    ligne1.Point = new Point(pt3.X, pt3.Y);
    ligne2.Point = new Point(pt1.X, pt1.Y);
    pathfigure1.StartPoint = new Point(pt1.X, pt1.Y);
    pathfigure1.Segments.Add(arc1);
    pathfigure1.Segments.Add(ligne1);
    pathfigure1.Segments.Add(arc2);
    pathfigure1.Segments.Add(ligne2);
    pathGeometry.Figures.Add(pathfigure1);
    arc_path1.Data = pathGeometry;
    arc_path1.Tag = percage;

    percage.ListShapes.Add(arc_path1);

}
else
{
    Ellipse ellipse = new Ellipse();
    ellipse.Stroke = System.Windows.Media.Brushes.Red;
    ellipse.StrokeThickness = 1;
    ellipse.Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Red);
    ellipse.Width = percage.Diametre;
    ellipse.Height = percage.Diametre;
    percage.Coor_X_Graph = X1 + dx - (percage.Diametre / 2);
    percage.Coor_Y_Graph = this.MyScrollViewer.ActualHeight * echelle - (Y1 + dy) - (percage.Diametre / 2);
    ellipse.Margin = new System.Windows.Thickness(percage.Coor_X_Graph, percage.Coor_Y_Graph, 0, 0);
    ellipse.Tag = percage;

    percage.ListShapes.Add(ellipse);
}

然后,为了获得最接近的形状,我开始编写代码: 对于椭圆我可以检索它的坐标,但对于路径,找不到里面的段列表。

StartPoint = e.GetPosition(monDessin);
double distance=-1;
Shape selectedShape = null;
for (int i = monDessin.Children.Count - 1; i > -1; i--)
{

    if (monDessin.Children[i] is Ellipse)
    {
        Ellipse ell = (Ellipse)monDessin.Children[i];
        double x = ell.Margin.Left + Width / 2;
        double y = ell.Margin.Top - ell.Height / 2;
        double dist = Math.Sqrt((StartPoint.X - x) * (StartPoint.X - x) + (StartPoint.Y -y) * (StartPoint.Y - y));
        if(distance==-1 || dist<distance)
        {
            distance = dist;
        }
    }
    else if(monDessin.Children[i] is Path)
    {
        Path path=(Path)monDessin.Children[i];
        Geometry geometry = path.Data;
        foreach(PathFigure pf in ?????)
    }
}

【问题讨论】:

    标签: c# canvas shape


    【解决方案1】:

    最后,我可以自己在互联网上多看一点(不确定这是我开始研究该主题时的最佳方式,所以欢迎任何其他建议)

    我找到了一些“解决方案”here 但是代码不起作用,在下一行出现错误(不明白为什么,也不知道它做了什么)

    string value = seralizer.ConvertToString(geomerty, null);
    

    最后我在 msdn 网站上对其进行了修改,我发现 geometry.GetOutlinedPathGeometry()pathGeometry.Figures 可以获取数字列表。我只是不明白为什么我所有的 ArcSegment 都变成了 BezierSegment。 无论如何,它工作正常,所以我把代码放在这里:

    StartPoint = e.GetPosition(monDessin);
    double distance=-1;
    double dist;
    Shape selectedShape = null;
    for (int i = monDessin.Children.Count - 1; i > -1; i--)
    {
        string type = monDessin.Children[i].GetType().ToString();
    
        if (monDessin.Children[i] is Ellipse)
        {
            Ellipse ell = (Ellipse)monDessin.Children[i];
            double x = ell.Margin.Left + ell.Width / 2;
            double y = ell.Margin.Top - ell.Height / 2;
            dist = Math.Sqrt((StartPoint.X - x) * (StartPoint.X - x) + (StartPoint.Y -y) * (StartPoint.Y - y));
            if(distance==-1 || dist<distance)
            {
                distance = dist;
            }
        }
        else if(monDessin.Children[i] is Path)
            {
                Path path=(Path)monDessin.Children[i];
                string titi = path.Tag.GetType().ToString();
                Geometry geometry = path.Data;
                PathGeometry pathGeometry = geometry.GetOutlinedPathGeometry();
                PathFigureCollection figures = pathGeometry.Figures;
                if (figures != null)
                {
                   foreach (PathFigure figure in figures)
                   {
                       foreach (PathSegment segment in figure.Segments)
                       {
                           //first syntax : if(segment is LineSegment)
                           if(segment is LineSegment)
                           {
                              LineSegment lineSegment = (LineSegment)segment;
                              double x = lineSegment.Point.X;
                              ouble y = lineSegment.Point.Y;
                           }
                           //2nd syntax : 
                           //ArcSegment arcSegment = segment as ArcSegment;
                           //Then check if not null
                           ArcSegment arcSegment = segment as ArcSegment;
                           if (arcSegment != null)
                           {
                               double x = arcSegment.Point.X;
                               double y = arcSegment.Point.Y;
                               dist = Math.Sqrt((StartPoint.X - x) * (StartPoint.X - x) + (StartPoint.Y - y) * (StartPoint.Y - y));
                               if (distance == -1 || dist < distance)
                               {
                                   distance = dist;
                               }
                           }
                           BezierSegment bezierSegment = segment as BezierSegment;
                           if (bezierSegment != null)
                           {
                               double x = bezierSegment.Point3.X;
                               double y = bezierSegment.Point3.Y;
                               dist = Math.Sqrt((StartPoint.X - x) * (StartPoint.X - x) + (StartPoint.Y - y) * (StartPoint.Y - y));
                               if (distance == -1 || dist < distance)
                               {
                                    distance = dist;
                               }
                           }
                       }
                  }
              }
         }
    }
    

    注意:我发现了两种不同的语法来检查段的类型(即 LineSegment),我不知道哪个是最好的方法,第一种语法似乎更好,但第二种语法有优势来检查它是否是null(即使理论上它可能永远不会发生???)

    【讨论】:

      猜你喜欢
      • 2011-07-09
      • 2014-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 2012-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多