static void PointIsClosestExperiment(
            Vector point,
            VertexConstraints point1Constraints,
            VertexConstraints point2Constraints,
            string fileName)
        {
            Console.WriteLine(string.Format("Doing experiment for {0}", fileName));

            Bitmap    image      = new Bitmap(320, 240);
            const int iterations = 200000;

            using (Graphics graphics = Graphics.FromImage(image))
            {
                for (int i = 0; i < iterations; ++i)
                {
                    Vector point1 = new Vector(
                        point1Constraints.MinCoord.X + (point1Constraints.MaxCoord.X - point1Constraints.MinCoord.X) * Random.Double(),
                        point1Constraints.MinCoord.Y + (point1Constraints.MaxCoord.Y - point1Constraints.MinCoord.Y) * Random.Double());
                    Vector point2 = new Vector(
                        point2Constraints.MinCoord.X + (point2Constraints.MaxCoord.X - point2Constraints.MinCoord.X) * Random.Double(),
                        point2Constraints.MinCoord.Y + (point2Constraints.MaxCoord.Y - point2Constraints.MinCoord.Y) * Random.Double());

                    double distanceSqr, alpha;
                    point.DistanceToSegmentSquared(point1, point2, out distanceSqr, out alpha);
                    alpha = MathHelper.Trunc(alpha, 0, 1);
                    Vector      closestPoint = point1 + (point2 - point1) * alpha;
                    const float radius       = 2;
                    graphics.FillEllipse(
                        Brushes.Green,
                        (float)closestPoint.X - radius,
                        (float)closestPoint.Y - radius,
                        radius * 2,
                        radius * 2);
                }

                graphics.DrawRectangle(
                    Pens.Blue,
                    point1Constraints.CoordRectangle.Left,
                    point1Constraints.CoordRectangle.Top,
                    point1Constraints.CoordRectangle.Width,
                    point1Constraints.CoordRectangle.Height);
                graphics.DrawRectangle(
                    Pens.Blue,
                    point2Constraints.CoordRectangle.Left,
                    point2Constraints.CoordRectangle.Top,
                    point2Constraints.CoordRectangle.Width,
                    point2Constraints.CoordRectangle.Height);
                graphics.FillEllipse(Brushes.Red, (float)point.X - 2, (float)point.Y - 2, 4, 4);
            }

            image.Save(fileName);
        }
        public LengthAngleSpaceSeparator(
            Vector segmentStart, Vector segmentEnd, Vector point, double allowedLength, double allowedAngle, bool swapDirection)
        {
            if (allowedAngle < -Math.PI || allowedAngle > Math.PI)
                throw new ArgumentOutOfRangeException("allowedAngle", "Allowed angle should be in [-pi, pi] range.");
            if (allowedLength < 0)
                throw new ArgumentOutOfRangeException("allowedLength", "Allowed length should be positive.");
            if ((segmentStart - segmentEnd).LengthSquared < 1e-6)
                throw new ArgumentException("Given segment must have non-zero length!");
            
            double distanceToSegmentSqr, alpha;
            point.DistanceToSegmentSquared(segmentStart, segmentEnd, out distanceToSegmentSqr, out alpha);

            Vector zeroAngleVec = segmentStart + (segmentEnd - segmentStart) * alpha - point;
            this.distanceSqr = zeroAngleVec.LengthSquared;

            if (this.distanceSqr < 1e-6)
            {
                this.singularMode = true;
                
                double angle = Vector.AngleBetween(Vector.UnitX, segmentEnd - segmentStart);
                double minAngle, maxAngle;
                if (angle < 0)
                {
                    minAngle = angle;
                    maxAngle = angle + Math.PI;
                }
                else
                {
                    maxAngle = angle;
                    minAngle = angle - Math.PI;
                }

                singularModeAngleRange = new Range(minAngle, maxAngle);
                if (!singularModeAngleRange.Contains(allowedAngle))
                    singularModeAngleRange = singularModeAngleRange.Invert();
            }
            else
            {
                this.singularMode = false;

                this.angleOffset = -Vector.AngleBetween(Vector.UnitX, zeroAngleVec);
                double offsetedAllowedAngle = this.OffsetAngle(allowedAngle);
                if (offsetedAllowedAngle < -Math.PI * 0.5 || offsetedAllowedAngle > Math.PI * 0.5)
                    throw new ArgumentOutOfRangeException("allowedAngle", "After translation to the coordinate system of the given segment, allowed angle must be in [-pi/2, pi/2] range.");
                this.sign = Math.Sign(this.SeparationValue(allowedLength, offsetedAllowedAngle));
            }

            this.swapDirection = swapDirection;
        }
 private static void MinMaxDistanceForEdge(
     Vector point,
     Polygon convexHull,
     VertexConstraints constraints1,
     VertexConstraints constraints2,
     out double minDistanceSqr,
     out double maxDistanceSqr)
 {
     if (convexHull.IsPointInside(point))
         minDistanceSqr = 0;
     else
     {
         minDistanceSqr = Double.PositiveInfinity;
         for (int i = 0; i < convexHull.Vertices.Count; ++i)
         {
             double distanceSqr = point.DistanceToSegmentSquared(
                 convexHull.Vertices[i],
                 convexHull.Vertices[(i + 1) % convexHull.Vertices.Count]);
             minDistanceSqr = Math.Min(minDistanceSqr, distanceSqr);
         }
     }
     
     maxDistanceSqr = 0;
     foreach (Vector vertex1 in constraints1.Corners)
     {
         foreach (Vector vertex2 in constraints2.Corners)
         {
             double distanceSqr = point.DistanceToSegmentSquared(vertex1, vertex2);
             maxDistanceSqr = Math.Max(maxDistanceSqr, distanceSqr);
         }
     }
 }
        static void PointIsClosestExperiment(
            Vector point,
            VertexConstraints point1Constraints,
            VertexConstraints point2Constraints,
            string fileName)
        {
            Console.WriteLine(string.Format("Doing experiment for {0}", fileName));

            Bitmap image = new Bitmap(320, 240);
            const int iterations = 200000;
            using (Graphics graphics = Graphics.FromImage(image))
            {
                for (int i = 0; i < iterations; ++i)
                {
                    Vector point1 = new Vector(
                        point1Constraints.MinCoord.X + (point1Constraints.MaxCoord.X - point1Constraints.MinCoord.X) * Random.Double(),
                        point1Constraints.MinCoord.Y + (point1Constraints.MaxCoord.Y - point1Constraints.MinCoord.Y) * Random.Double());
                    Vector point2 = new Vector(
                        point2Constraints.MinCoord.X + (point2Constraints.MaxCoord.X - point2Constraints.MinCoord.X) * Random.Double(),
                        point2Constraints.MinCoord.Y + (point2Constraints.MaxCoord.Y - point2Constraints.MinCoord.Y) * Random.Double());

                    double distanceSqr, alpha;
                    point.DistanceToSegmentSquared(point1, point2, out distanceSqr, out alpha);
                    alpha = MathHelper.Trunc(alpha, 0, 1);
                    Vector closestPoint = point1 + (point2 - point1) * alpha;
                    const float radius = 2;
                    graphics.FillEllipse(
                        Brushes.Green,
                        (float)closestPoint.X - radius,
                        (float)closestPoint.Y - radius,
                        radius * 2,
                        radius * 2);
                }

                graphics.DrawRectangle(
                    Pens.Blue,
                    point1Constraints.CoordRectangle.Left,
                    point1Constraints.CoordRectangle.Top,
                    point1Constraints.CoordRectangle.Width,
                    point1Constraints.CoordRectangle.Height);
                graphics.DrawRectangle(
                    Pens.Blue,
                    point2Constraints.CoordRectangle.Left,
                    point2Constraints.CoordRectangle.Top,
                    point2Constraints.CoordRectangle.Width,
                    point2Constraints.CoordRectangle.Height);
                graphics.FillEllipse(Brushes.Red, (float)point.X - 2, (float)point.Y - 2, 4, 4);
            }

            image.Save(fileName);
        }
 public double CalculateBackgroundPenaltyForEdge(Vector point, double edgeWidth, Vector edgePoint1, Vector edgePoint2)
 {
     double distanceSqr = point.DistanceToSegmentSquared(edgePoint1, edgePoint2);
     return CalculateBackgroundPenaltyForEdge(distanceSqr, edgeWidth);
 }