Plotting an ArcSegment (or any PathGeometry) correctly

Dec 2, 2009 at 9:16 PM

Hi,

I have a list of lines and circular arcs that I want to plot. But I couldn't manage to plot ArcSegment (for circular arcs) successfully. I've looked at the samples and found that whenever a System.Window.Shapes element is plotted a ViewportHostPanel or ViewportPanel is used. I don't know what they are used for but I've tried the same for my Path object which holds the arcSegment but it didn't work. The thing is the lines are are fit to ChartPlotter and the size and position is correct according to axes but for arcSegment neither the size nor the position is correct.

I've used the below code to dynamically do this but as I said it doesn't work (here I didn't use ViewportPanel or ViewportHostPanel since I couldn't make them work):

private void tbtnLoad_Click(object sender, RoutedEventArgs e) {
  AddLineGraph(new Point(0, 0), new Point(0, 50));
  AddCircularArcGraph(new Point(0, 0), new Point(50, 50), new Size(30, 30));
  AddLineGraph(new Point(50, 50), new Point(0, 50));
}

private void AddLineGraph(Point startPoint, Point endPoint) {
  var ds = new EnumerableDataSource<Point>(new List<Point> {
        new Point { X = startPoint.X, Y = startPoint.Y }, 
        new Point { X = endPoint.X, Y = endPoint.Y } 
      });
  ds.SetXYMapping(pt => pt);

  cpGeometries.AddLineGraph(ds);
}

private void AddCircularArcGraph(Point startPoint, Point endPoint, Size size) {
  PathFigure pf = new PathFigure();
  pf.StartPoint = new Point(startPoint.X, startPoint.Y);

  ArcSegment arcSegment = new ArcSegment();
  arcSegment.Point = new Point(endPoint.X, endPoint.Y);
  arcSegment.Size = size;
  arcSegment.SweepDirection = SweepDirection.Clockwise;

  PathSegmentCollection psc = new PathSegmentCollection();
  psc.Add(arcSegment);

  pf.Segments = psc;

  PathFigureCollection pfc = new PathFigureCollection();
  pfc.Add(pf);

  PathGeometry pg = new PathGeometry();
  pg.Figures = pfc;

  var path = new Path();
  path.Stroke = Brushes.Black;
  path.StrokeThickness = 1;
  path.Data = pg;

  //var vp = new ViewportHostPanel();
  //vp.SetValue(ViewportHostPanel.XProperty, 0.2);
  //vp.SetValue(ViewportHostPanel.YProperty, 0.2);
  //vp.SetValue(ViewportHostPanel.WidthProperty, arcSegment.Size.Width * 2);
  //vp.SetValue(ViewportHostPanel.HeightProperty, arcSegment.Size.Height * 2);

  //vp.Children.Add(path);
  //cpGeometries.Children.Add(vp);
  cpGeometries.Children.Add(path);
}

Can anybody point me in the right direction?

Thanks in advance

Dec 6, 2009 at 11:31 AM

There is no one that has any idea? I'm really stuck and run out of ideas :(

Thanks

Editor
Dec 7, 2009 at 7:48 PM

 

Hi,

I have modified a little your code to make it correct and reach your desired target, as I understood it:

 

private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			AddLineGraph(new Point(0, 0), new Point(0, 50));
			AddCircularArcGraph(new Point(0, 0), new Point(50, -50), new Size(50, 50));
			AddLineGraph(new Point(50, 50), new Point(0, 50));
		}

		private void AddLineGraph(Point startPoint, Point endPoint)
		{
			var ds = new EnumerableDataSource<Point>(new List<Point> {
        new Point { X = startPoint.X, Y = startPoint.Y }, 
        new Point { X = endPoint.X, Y = endPoint.Y } 
      });
			ds.SetXYMapping(pt => pt);

			plotter.AddLineGraph(ds);
		}

		private void AddCircularArcGraph(Point startPoint, Point endPoint, Size size)
		{
			PathFigure pf = new PathFigure();
			pf.StartPoint = new Point(startPoint.X, startPoint.Y);

			ArcSegment arcSegment = new ArcSegment();
			arcSegment.Point = new Point(endPoint.X, endPoint.Y);
			arcSegment.Size = size;
			arcSegment.SweepDirection = SweepDirection.Counterclockwise;

			PathSegmentCollection psc = new PathSegmentCollection();
			psc.Add(arcSegment);

			pf.Segments = psc;

			PathFigureCollection pfc = new PathFigureCollection();
			pfc.Add(pf);

			PathGeometry pg = new PathGeometry();
			pg.Figures = pfc;

			var path = new Path();
			path.Stroke = Brushes.Black;
			path.StrokeThickness = 1;
			path.Data = pg;
			path.Fill = Brushes.Orange;
			path.Stretch = Stretch.Fill;

			var viewportPanel = new ViewportHostPanel();
			ViewportPanel.SetViewportBounds(path, new DataRect(0, 0, 50, 50));
			viewportPanel.Children.Add(path);
			plotter.Children.Add(viewportPanel);
		}

PathSegment has one negative coordinate, because in WPF screen coordinates' Y axis goes from top of the screen to its bottom, and in D3 Y axis goes in natural mathematical way - from bottom to top.

Hope this will help.

Best regards,

Mikhail.

 

Dec 7, 2009 at 11:39 PM

Thanks so much for the help. I would have never figured out the part with ViewportHostPanel and path.Stretch.

Jan 12, 2010 at 10:30 AM
Edited Jan 12, 2010 at 7:09 PM

Hi,

It's been long time but I wanted to ask one more thing about the code above: In AddCircularGraphMethod method we specify viewport bounds as:
ViewportPanel.SetViewportBounds(path, new DataRect(0, 0, 50, 50));
How do we find the values (0, 0, 50, 50)?
I have lots of lines and arcs that are connected but they are not plotted as connected. The bounds surely come from the start, end and size values but I couldn't figure this out. For example I wasn't able to plot these two lines and arc as connected (which should be connected):
AddLineGraph(nPointD(0.164141472, 1.44), new PointD(0.201979003, 1.556451947));
AddCircularArcGraph(new PointD(0.201979003, 1.556451947), new PointD(0.198936336, 1.5671688), new PointD(0.192468438, 1.559542117));
AddLineGraph(new PointD(0.198936336, 1.5671688), new PointD(0.169118814, 1.592455898)Thi

It's been long time but I wanted to ask one more thing about the code above: In AddCircularGraphMethod method we specify viewport bounds as:

ViewportPanel.SetViewportBounds(path, new DataRect(0, 0, 50, 50));

How do we find the values (0, 0, 50, 50)?

I have lots of lines and arcs that are connected but they are not plotted as connected. The bounds surely come from the start, end and size values but I couldn't figure this out. For example I wasn't able to plot these two lines and arc as connected (which are be connected):

AddLineGraph(new PointD(0.164141472, 1.44), new PointD(0.201979003, 1.556451947));
AddCircularArcGraph(new PointD(0.201979003, 1.556451947), new PointD(0.198936336, 1.5671688), new PointD(0.192468438, 1.559542117));
AddLineGraph(new PointD(0.198936336, 1.5671688), new PointD(0.169118814, 1.592455898));

How can manage to plot them successfully as connected entities?

By the way, I've changed the above code a little bit: The third parameter of AddCircularArcGraph method takes the center point instead of size and also multiplied Y ordinals by -1 to adjust with WPF coordinate system. But the viewportPanel.SetViewportBounds part doesn't seem to work:

    private void AddCircularArcGraph(Point startPoint, Point endPoint, PointD centerPoint) {
      PathFigure pf = new PathFigure();
      pf.StartPoint = new Point(startPoint.X, startPoint.Y * -1);

      ArcSegment arcSegment = new ArcSegment();
      arcSegment.Point = new Point(endPoint.X, endPoint.Y * -1);
      arcSegment.SweepDirection = SweepDirection.Counterclockwise;
      arcSegment.IsLargeArc = false;

      var radius = Math.Sqrt(Math.Pow(startPoint.X - centerPoint.X, 2) + Math.Pow(startPoint.Y - centerPoint.Y, 2));
      arcSegment.Size = new Size(radius, radius);

      PathSegmentCollection psc = new PathSegmentCollection();
      psc.Add(arcSegment);

      pf.Segments = psc;

      PathFigureCollection pfc = new PathFigureCollection();
      pfc.Add(pf);

      PathGeometry pg = new PathGeometry();
      pg.Figures = pfc;

      var path = new Path();
      path.Stroke = Brushes.Black;
      path.StrokeThickness = 1;
      path.Data = pg;
      path.Fill = Brushes.Orange;
      path.Stretch = Stretch.Fill;

      var viewportPanel = new ViewportHostPanel();
      viewportPanel.SetViewportBounds(path, new DataRect(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y), radius, radius));
      viewportPanel.Children.Add(path);
      plotter.Children.Add(viewportPanel);
    }

Thanks in advance

Feb 15, 2010 at 5:46 PM

Hi,

I've asked this followup question a while ago but didn't get any answer and I still couldn't find out how to set viewport bounds of a ViewportHostPanel that will hold an ArcSegment.

Can anyone help?

Thanks in advance