Search code examples
c#wpfoxyplot

Is it possible to have smoother contour lines with the ContourSeries in OxyPlot?


I used OxyPlot for drawing contours, but they seem a little rough at some places, so I would need to smooth them. So, I was wondering if it was possible to smooth the contour with OxyPlot or if I will need something else?

I know that you can smooth the LineSeries, so by looking inside the code for the LineSeries I have tried to put the code for smoothing in the ContourSeries, but I am not quite able to figure out how everything works. I tried to find smoothing algorithm on the internet, but I wasn't able to find many and those that I tried didn't work at all.

Also, I have tried to look for another library for drawing contours, but OxyPlot seems to be the best for free for WPF, but if you have other suggestions that can give me better results I would appreciate it.


Solution

  • After some more searching I found an algorithm that did a pretty good job, but some lines that needed to be closed were not, but the performance were really good by comparing to other algorithms I tried.

    Here's the algorithm

    private void SmoothContour(List<DataPoint> points, int severity = 1)
        {
            for (int i = 1; i < points.Count; i++)
            {
                var start = (i - severity > 0 ? i - severity + 1 : 0);
                var end = (i + severity < points.Count ? i + severity + 1 : points.Count);
    
                double sumX = 0, sumY = 0;
    
                for (int j = start; j < end; j++)
                {
                    sumX += points[j].X;
                    sumY += points[j].Y;
                }
    
                DataPoint sum = new DataPoint(sumX, sumY);
    
                DataPoint avg = new DataPoint(sum.X / (end - start), sum.Y / (end - start));
    
                points[i] = avg;
    
            }
        }
    

    It's based on this method: https://stackoverflow.com/a/18830268/11788646

    After that I put this method in the ContourSeries class like this :

    List<Contour> smoothedContours = new List<Contour>();
    
    for (int i = 0; i < contours.Count; i++)
    {
        List<DataPoint> smoothedPoints = new List<DataPoint>(contours[i].Points);
    
        for (int j = 0; j < SmoothLevel; j++)
        {
            SmoothContour(smoothedPoints);
        }
    
        Contour contour = new Contour(smoothedPoints, contours[i].ContourLevel);
        smoothedContours.Add(contour);
    }
    
    contours = smoothedContours;
    

    It's located in the CalculateContours() method just after the call of the JoinContourSegments() method. I also added a SmoothLevel property to add more smoothing to the lines. The higher it is the smoother the lines are, but when it is set too high, it doesn't do too well. So I keep at 10 and it's good.