void CheckOffset(double x0, double y0, double x1, double y1, double segFrac, double offset,
            double expectedX, double expectedY)
        {
            LineSegment seg = new LineSegment(x0, y0, x1, y1);
            Coordinate p = seg.PointAlongOffset(segFrac, offset);

            Assert.IsTrue(EqualsTolerance(new Coordinate(expectedX, expectedY), p, 0.000001));
        }
        /// <summary>
        /// Adds a limited mitre join connecting the two reflex offset segments.
        /// A limited mitre is a mitre which is beveled at the distance
        /// determined by the mitre ratio limit.
        /// </summary>
        /// <param name="offset0">The first offset segment</param>
        /// <param name="offset1">The second offset segment</param>
        /// <param name="distance">The offset distance</param>
        /// <param name="mitreLimit">The mitre limit ratio</param>
        private void AddLimitedMitreJoin(
            LineSegment offset0,
            LineSegment offset1,
            double distance,
            double mitreLimit)
        {
            var basePt = _seg0.P1;

            var ang0 = AngleUtility.Angle(basePt, _seg0.P0);
            //var ang1 = AngleUtility.Angle(basePt, _seg1.P1);

            // oriented angle between segments
            var angDiff = AngleUtility.AngleBetweenOriented(_seg0.P0, basePt, _seg1.P1);
            // half of the interior angle
            var angDiffHalf = angDiff / 2;

            // angle for bisector of the interior angle between the segments
            var midAng = AngleUtility.Normalize(ang0 + angDiffHalf);
            // rotating this by PI gives the bisector of the reflex angle
            var mitreMidAng = AngleUtility.Normalize(midAng + Math.PI);

            // the miterLimit determines the distance to the mitre bevel
            var mitreDist = mitreLimit * distance;
            // the bevel delta is the difference between the buffer distance
            // and half of the length of the bevel segment
            var bevelDelta = mitreDist * Math.Abs(Math.Sin(angDiffHalf));
            var bevelHalfLen = distance - bevelDelta;

            // compute the midpoint of the bevel segment
            var bevelMidX = basePt.X + mitreDist * Math.Cos(mitreMidAng);
            var bevelMidY = basePt.Y + mitreDist * Math.Sin(mitreMidAng);
            var bevelMidPt = new Coordinate(bevelMidX, bevelMidY);

            // compute the mitre midline segment from the corner point to the bevel segment midpoint
            var mitreMidLine = new LineSegment(basePt, bevelMidPt);

            // finally the bevel segment endpoints are computed as offsets from
            // the mitre midline
            var bevelEndLeft = mitreMidLine.PointAlongOffset(1.0, bevelHalfLen);
            var bevelEndRight = mitreMidLine.PointAlongOffset(1.0, -bevelHalfLen);

            if (_side == Positions.Left)
            {
                _segList.AddPt(bevelEndLeft);
                _segList.AddPt(bevelEndRight);
            }
            else
            {
                _segList.AddPt(bevelEndRight);
                _segList.AddPt(bevelEndLeft);
            }
        }
        private static Coordinate[] GenerateSegmentCurve(Coordinate p0, Coordinate p1,
            double width0, double width1)
        {
            var seg = new LineSegment(p0, p1);

            var dist0 = width0 / 2;
            var dist1 = width1 / 2;
            var s0 = seg.PointAlongOffset(0, dist0);
            var s1 = seg.PointAlongOffset(1, dist1);
            var s2 = seg.PointAlongOffset(1, -dist1);
            var s3 = seg.PointAlongOffset(0, -dist0);

            Coordinate[] pts = { s0, s1, s2, s3, s0 };

            return pts;
        }