Пример #1
0
    private static FuzzySet Merge(FuzzySet fs1, FuzzySet fs2, Func <double, double, double> MergeFt)
    {
        // New Fuzzy set
        FuzzySet result = new FuzzySet(Math.Min(fs1.Min, fs2.Min), Math.Max(fs1.Max, fs2.Max));

        // Creation of iterators on lists + initialization
        List <Point2D> .Enumerator enum1 = fs1.Points.GetEnumerator();
        List <Point2D> .Enumerator enum2 = fs2.Points.GetEnumerator();
        enum1.MoveNext();
        enum2.MoveNext();
        Point2D oldPt1 = enum1.Current;

        // Relative positions of fuzzy sets (to know when they intersect)
        int relativePosition    = 0;
        int newRelativePosition = Math.Sign(enum1.Current.Y - enum2.Current.Y);

        // Loop while there are points in the two collections
        Boolean endOfList1 = false;
        Boolean endOfList2 = false;

        while (!endOfList1 && !endOfList2)
        {
            // New x values
            double x1 = enum1.Current.X;
            double x2 = enum2.Current.X;
            // New current position
            relativePosition    = newRelativePosition;
            newRelativePosition = Math.Sign(enum1.Current.Y - enum2.Current.Y);

            if (relativePosition != newRelativePosition && relativePosition != 0 && newRelativePosition != 0)
            {
                // Positions have changed, so we have to compute the intersection and add it
                // Compute the points coordinates
                double x      = (x1 == x2 ? oldPt1.X : Math.Min(x1, x2));
                double xPrime = Math.Max(x1, x2);
                // Intersection
                double slope1 = (fs1.DegreeAtValue(xPrime) - fs1.DegreeAtValue(x)) / (xPrime - x);
                double slope2 = (fs2.DegreeAtValue(xPrime) - fs2.DegreeAtValue(x)) / (xPrime - x);
                double delta  = (fs2.DegreeAtValue(x) - fs1.DegreeAtValue(x)) / (slope1 - slope2);
                // Add point
                result.Add(x + delta, fs1.DegreeAtValue(x + delta));
                // Go on
                if (x1 < x2)
                {
                    oldPt1     = enum1.Current;
                    endOfList1 = !(enum1.MoveNext());
                }
                else if (x1 > x2)
                {
                    endOfList2 = !(enum2.MoveNext());
                }
            }
            else if (x1 == x2)
            {
                // The two points are on the same X, so we take the good value (eg min or max)
                result.Add(x1, MergeFt(enum1.Current.Y, enum2.Current.Y));
                oldPt1     = enum1.Current;
                endOfList1 = !(enum1.MoveNext());
                endOfList2 = !(enum2.MoveNext());
            }
            else if (x1 < x2)
            {
                // Fs1 point is first, we add the value (eg min or max) between the enum1 point and the degree for fs2
                result.Add(x1, MergeFt(enum1.Current.Y, fs2.DegreeAtValue(x1)));
                oldPt1     = enum1.Current;
                endOfList1 = !(enum1.MoveNext());
            }
            else
            {
                // This time, it's fs2 first
                result.Add(x2, MergeFt(fs1.DegreeAtValue(x2), enum2.Current.Y));
                endOfList2 = !(enum2.MoveNext());
            }
        }

        // Add end points
        if (!endOfList1)
        {
            while (!endOfList1)
            {
                result.Add(enum1.Current.X, MergeFt(0, enum1.Current.Y));
                endOfList1 = !enum1.MoveNext();
            }
        }
        else if (!endOfList2)
        {
            while (!endOfList2)
            {
                result.Add(enum2.Current.X, MergeFt(0, enum2.Current.Y));
                endOfList2 = !enum2.MoveNext();
            }
        }

        return(result);
    }