代码之家  ›  专栏  ›  技术社区  ›  Siegfried.V

从pathgeometry获取list<segment>

  •  0
  • Siegfried.V  · 技术社区  · 6 年前

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

    现在,当我点击我的画布,我想得到最近的形状。

    我可以为椭圆做点什么,但对于路径,我找不到如何得到它的坐标。

    下面是我用来生成列表的代码,以防在该方法中出现问题:

    具体来说,“perage”是钻孔,如果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 ?????)
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Siegfried.V    6 年前

    最后,我可以自己在网上多看一点(不确定这是最好的方式,因为我开始讨论这个主题,所以欢迎任何其他建议)

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

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

    最后我在msdn网站上修改了它,我发现 geometry.GetOutlinedPathGeometry() pathGeometry.Figures 这样就可以得到数字列表。我只是不明白为什么我所有的弧段都变成了贝塞尔段。 不管怎样,它工作得很好,所以我把代码放在这里:

    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;
                               }
                           }
                       }
                  }
              }
         }
    }
    

    注:我发现了两种不同的语法来检查段的类型(即行段),我不知道哪种是最好的方法,第一种语法看起来更好,但第二种语法的优点是检查它是否为空(即使在理论上它可能永远不会发生)???)