Question

I've created a SortedSet<ALine> object, however, when calling S.Remove(S.First()) the first element of the set is not removed. I've encountered this problem before and back then it related to the ALine.CompareTo method not being implemented correctly (the function never returned 0 because two lines with the same length shouldn't be treated as equal), however after fixing it the problem still occurs with some of my tests (not all!).

The ALine class can be found at the bottom.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algoritme.Model
{
    /// <summary>
    /// This class represents a line between two points.
    /// </summary>
    public class ALine : IComparable<ALine>
    {
        public APoint Point1 { get; set; }
        public APoint Point2 { get; set; }
        public int NumTerminals { get; private set; }

        /// <summary>
        /// Constructor using two points
        /// </summary>
        /// <param name="p1">The starting point</param>
        /// <param name="p2">The ending point</param>
        public ALine(APoint p1, APoint p2)
        {
            if (!p1.Equals(p2))
            {
                this.Point1 = p1;
                this.Point2 = p2;

                if (p1.GetType() == typeof(ATerminalPoint))
                {
                    NumTerminals = NumTerminals + 1;
                }
                if (p2.GetType() == typeof(ATerminalPoint))
                {
                    NumTerminals = NumTerminals + 1;
                }
            }
            else
            {
                throw new ArgumentException("Start and end points may not be the same");
            }
        }

        /// <summary>
        /// Constructor using four icoordinates
        /// </summary>
        /// <param name="x1">The x coordinate of the starting point</param>
        /// <param name="y1">The y coordinate of the starting point</param>
        /// <param name="x2">The x coordinate of the ending point</param>
        /// <param name="y2">The y coordinate of the ending point</param>
        public ALine(int x1, int y1, int x2, int y2)
        {
            this.Point1 = new APoint(x1, y1);
            this.Point2 = new APoint(x2, y2);
        }

        /// <summary>
        /// Calculates the length of a line, which is measured by the Euclidean distance between the start and end points of the line.
        /// </summary>
        /// <returns>Double containing the length of the line </returns>
        public double Length()
        {
            return Math.Sqrt(Math.Pow((Point2.X - Point1.X), 2) + Math.Pow((Point2.Y - Point1.Y), 2));
        }

        // override object.Equals
        public override bool Equals(Object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }

            return Equals(obj as ALine);
        }

        /// <summary>
        /// Check if the line equals another given line. Lines are considered equal when their start and end points are equal, or their inverse is.
        /// </summary>
        /// <param name="other">The line to check with</param>
        /// <returns></returns>
        public bool Equals(ALine other)
        {
            if ((this.Point1.Equals(other.Point1) && this.Point2.Equals(other.Point2)) || (this.Point2.Equals(other.Point1) && this.Point1.Equals(other.Point2)))
            {
                return true;
            }

            return false;
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return Point1.GetHashCode() ^ Point2.GetHashCode();
        }

        /// <summary>
        /// Lines are compared first by their length. If the length is equal, lines that connect TerminalPoints are preferred.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(ALine other)
        {
            if (this.Equals(other))
            {
                return 0;
            }
            else if (this.Length() > other.Length())
            {
                return 1;
            }
            else if (this.Length() < other.Length())
            {
                return -1;
            }
            // Count the number of TerminalPoints for each line.
            else if (this.NumTerminals > other.NumTerminals)
            {
                return -1;
            }
            else
            {
                return 1;
            }
        }
    }
}
Was it helpful?

Solution

After debugging it turned out that the comparison between S.First() and its successors returned 1, which - for some reason - meant that S thought its order was broken and therefore refused to remove the element.

Changing this.NumTerminals > other.NumTerminals to this.NumTerminals >= other.NumTerminals seems to have fixed the problem.

It is strange, however, that no specific feedback is presented to the user when such a thing happens. Anyway, thanks Marshall for the help!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top