public SlopeArcher(BaseVisualMode mode, List <IVisualEventReceiver> sectors, VisualSidedefSlope handle1, VisualSidedefSlope handle2, double theta, double offsetangle, double scale)
        {
            this.mode        = mode;
            this.sectors     = sectors;
            this.handle1     = handle1;
            this.handle2     = handle2;
            this.theta       = theta;
            this.offsetangle = offsetangle;
            this.scale       = scale;
            heightoffset     = 0.0;

            handleline = new Line2D(handle1.GetCenterPoint(), handle2.GetCenterPoint());
            length     = handleline.GetLength();

            if (handle1.Level.type == SectorLevelType.Ceiling)
            {
                baseheight = handle1.Level.extrafloor ? handle1.Level.sector.FloorHeight : handle1.Level.sector.CeilHeight;
            }
            else
            {
                baseheight = handle1.Level.extrafloor ? handle1.Level.sector.CeilHeight : handle1.Level.sector.FloorHeight;
            }

            baseheightoffset = 0.0;
        }
        /// <summary>
        /// Applies the slopes to the sectors.
        ///
        /// We have:
        /// - theta
        /// - offset angle ("offset")
        /// - horizontal line length ("length")
        ///
        /// What we need to compute:
        /// - x coordinate where the line starts in the circle ("left", this is cos(theta + offset angle))
        /// - x coordinate where the line ends in the circle ("middle", this is cos(offset angle))
        ///
        /// With this data we can calculate some more required variables:
        /// - radius: length / (middle - left)
        /// - left delimiter: cos(offset + theta) * radius
        /// - right delimiter: cos(rotation) * radius (should be same as left delimiter + length)
        /// - section start, in map units: cos(offset + theta) * radius
        /// - base height offset (where the slope starts)
        ///
        /// Then we can simply use pythagoras to compute the y position for an x position on the length
        /// </summary>
        public void ApplySlope()
        {
            double left   = Math.Cos(theta + offsetangle);
            double middle = Math.Cos(offsetangle);

            double radius         = length / (middle - left);
            double leftdelimiter  = Math.Cos(offsetangle + theta);
            double rightdelimiter = Math.Cos(offsetangle);

            double sectionstart = Math.Cos(offsetangle + theta) * radius;

            baseheightoffset = Math.Sqrt(radius * radius - sectionstart * sectionstart) * scale;

            foreach (BaseVisualGeometrySector bvgs in sectors)
            {
                HashSet <Vertex> vertices = new HashSet <Vertex>(bvgs.Sector.Sides.Count * 2);
                double           u1       = 1.0;
                double           u2       = 0.0;

                foreach (Sidedef sd in bvgs.Sector.Sides.Keys)
                {
                    vertices.Add(sd.Line.Start);
                    vertices.Add(sd.Line.End);
                }

                // Get the two points that are the furthest apart on the line between the slope handles
                foreach (Vertex v in vertices)
                {
                    double intersection = handleline.GetNearestOnLine(v.Position);

                    if (intersection < u1)
                    {
                        u1 = intersection;
                    }
                    if (intersection > u2)
                    {
                        u2 = intersection;
                    }
                }

                // Compute the x position and the corrosponding height of the coordinates
                double xpos1   = sectionstart + (u1 * length);
                double xpos2   = sectionstart + (u2 * length);
                double height1 = Math.Sqrt(radius * radius - xpos1 * xpos1) * scale;
                double height2 = Math.Sqrt(radius * radius - xpos2 * xpos2) * scale;

                if (double.IsNaN(height1))
                {
                    height1 = 0.0;
                }

                if (double.IsNaN(height2))
                {
                    height2 = 0.0;
                }

                // Adjust the heights
                height1 = height1 - baseheightoffset + baseheight + heightoffset;
                height2 = height2 - baseheightoffset + baseheight + heightoffset;

                // Get the angle of the slope. We cheat a bit and substitute the y value of the vectors with the height of the points
                double slopeangle = Vector2D.GetAngle(new Vector2D(xpos1, height1), new Vector2D(xpos2, height2));

                // Always let the plane point up, VisualSidedefSlope.ApplySlope will invert it if necessary
                Plane plane = new Plane(new Vector3D(handleline.GetCoordinatesAt(u1), height1), handleline.GetAngle() + Angle2D.PIHALF, slopeangle, true);

                VisualSidedefSlope.ApplySlope(bvgs.Level, plane, mode);

                bvgs.Sector.UpdateSectorGeometry(true);
            }
        }