public Circle(Vector center, double radius)
            : this()
        {
            Debug.Assert(radius >= 0);

            this.Center = center;
            this.Radius = radius;
        }
        public static Tuple<double, double> LineIntersection(Vector point1, Vector dir1, Vector point2, Vector dir2)
        {
            double denominator = Vector.CrossProduct(dir1, dir2);
            if (Math.Abs(denominator) < 1e-6)
                return null;

            double t1 = Vector.CrossProduct(dir2, point1 - point2) / denominator;
            double t2 = Vector.CrossProduct(dir1, point1 - point2) / denominator;
            return new Tuple<double, double>(t1, t2);
        }
        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;
        }
        public VertexConstraints(Vector minCoord, Vector maxCoord)
        {
            Debug.Assert(minCoord.X <= maxCoord.X && minCoord.Y <= maxCoord.Y);

            this.MinCoord = minCoord;
            this.MaxCoord = maxCoord;

            this.corners[0] = new Vector(this.MinCoord.X, this.MinCoord.Y);
            this.corners[1] = new Vector(this.MinCoord.X, this.MaxCoord.Y);
            this.corners[2] = new Vector(this.MaxCoord.X, this.MaxCoord.Y);
            this.corners[3] = new Vector(this.MaxCoord.X, this.MinCoord.Y);

            this.cornersReadOnly = new ReadOnlyCollection<Vector>(corners);
        }
        public Shape FitToSize(double width, double height)
        {
            Vector min = new Vector(Double.PositiveInfinity, Double.PositiveInfinity);
            Vector max = new Vector(Double.NegativeInfinity, Double.NegativeInfinity);
            foreach (Vector vertexPosition in vertexPositions)
            {
                min.X = Math.Min(min.X, vertexPosition.X);
                min.Y = Math.Min(min.Y, vertexPosition.Y);
                max.X = Math.Max(max.X, vertexPosition.X);
                max.Y = Math.Max(max.Y, vertexPosition.Y);
            }

            double widthRatio = width / (max.X - min.X);
            double heightRatio = height / (max.Y - min.Y);
            double scale = Math.Min(widthRatio, heightRatio);

            return this.Scale(scale, min);
        }
        private void SetupAnnealingSegmentationAlgorithm(AnnealingSegmentationAlgorithm algorithm)
        {
            algorithm.SolutionFitter.AnnealingProgress += OnAnnealingBasedSegmentatorProgress;

            if (!String.IsNullOrEmpty(this.segmentationProperties.InitialShape))
            {
                algorithm.StartShape = Shape.LoadFromFile(this.segmentationProperties.InitialShape);
            }
            else
            {
                double angle             = this.segmentationProperties.RootEdgeAngle;
                Vector rootEdgeDirection = new Vector(Math.Cos(angle), -Math.Sin(angle));
                algorithm.StartShape = algorithm.ShapeModel.FitMeanShape(
                    this.segmentedImage.Width, this.segmentedImage.Height, rootEdgeDirection);
            }

            this.SetupShapeMutator(algorithm.ShapeMutator);
            this.SetupAnnealing(algorithm.SolutionFitter);
        }
        public List<VertexConstraints> Split()
        {
            // We'll use it to split into non-intersecting sets
            const double eps = 1e-4;

            Vector middle = this.MiddleCoord;
            List<VertexConstraints> result = new List<VertexConstraints>();
            if (middle.X != MinCoord.X && middle.Y != MinCoord.Y)
                result.Add(new VertexConstraints(MinCoord, new Vector(middle.X - eps, middle.Y - eps)));
            if (middle.Y != MinCoord.Y)
                result.Add(new VertexConstraints(new Vector(middle.X + eps, MinCoord.Y), new Vector(MaxCoord.X, middle.Y - eps)));
            if (middle.X != MinCoord.X)
                result.Add(new VertexConstraints(new Vector(MinCoord.X, middle.Y + eps), new Vector(middle.X - eps, MaxCoord.Y)));
            result.Add(new VertexConstraints(new Vector(middle.X + eps, middle.Y + eps), MaxCoord));

            // We should split at least something
            Debug.Assert(result.Count >= 2);
            return result;
        }
        public static ShapeConstraints CreateFromBounds(
            ShapeStructure structure,
            Vector coordMin,
            Vector coordMax,
            double minEdgeWidth,
            double maxEdgeWidth)
        {
            ShapeConstraints result = new ShapeConstraints();
            result.ShapeStructure = structure;
            result.vertexConstraints = new List<VertexConstraints>();
            result.edgeConstraints = new List<EdgeConstraints>();

            for (int i = 0; i < structure.VertexCount; ++i)
                result.vertexConstraints.Add(new VertexConstraints(coordMin, coordMax));

            for (int i = 0; i < structure.Edges.Count; ++i)
                result.edgeConstraints.Add(new EdgeConstraints(minEdgeWidth, maxEdgeWidth));

            return result;
        }
        private void AddSeparatorsForPoint(Vector point, VertexConstraints constraint2, bool swapDirection)
        {
            this.separatorLists.Add(new List<LengthAngleSpaceSeparator>());

            Vector middlePoint = 0.5 * (constraint2.Corners[0] + constraint2.Corners[2]);

            for (int j = 0; j < 4; ++j)
            {
                Vector segmentStart = constraint2.Corners[j];
                Vector segmentEnd = constraint2.Corners[(j + 1) % 4];
                Vector segmentMiddle = 0.5 * (segmentStart + segmentEnd);
                Vector allowedPoint = segmentMiddle + (middlePoint - segmentMiddle) * 0.01;
                Vector allowedVec = allowedPoint - point;
                double allowedLength = allowedVec.Length;
                double allowedAngle = Vector.AngleBetween(Vector.UnitX, allowedVec);

                this.separatorLists[this.separatorLists.Count - 1].Add(
                    new LengthAngleSpaceSeparator(segmentStart, segmentEnd, point, allowedLength, allowedAngle, swapDirection));
            }
        }
        private void OnShapeCanvasMouseMove(object sender, MouseEventArgs e)
        {
            Point mousePos = e.GetPosition(this.shapeCanvas);

            if (this.controlledVertexIndex.HasValue)
            {
                this.shape.VertexPositions[this.controlledVertexIndex.Value] = new Vector(mousePos.X, mousePos.Y) - this.mouseOffset;
            }
            else if (this.controlledEdgeIndex.HasValue)
            {
                ShapeEdge edge = this.shape.Structure.Edges[this.controlledEdgeIndex.Value];
                double    distanceFromEdgeLine = new Vector(mousePos.X, mousePos.Y).DistanceToLine(
                    this.shape.VertexPositions[edge.Index1], this.shape.VertexPositions[edge.Index2]);
                this.shape.EdgeWidths[this.controlledEdgeIndex.Value] =
                    Math.Max(this.initialEdgeWidth + 2 * (distanceFromEdgeLine - this.initialDistanceFromEdgeLine), 5);
            }

            if (this.controlledVertexIndex.HasValue || this.controlledEdgeIndex.HasValue)
            {
                this.UpdateShapeControls();
            }
        }
        public int WindingNumber(Vector point)
        {
            int winding = 0;
            Vector prev = this.vertices[this.vertices.Count - 1];
            for (int i = 0; i < this.vertices.Count; ++i)
            {
                Vector cur = this.vertices[i];
                if (prev.Y <= point.Y)
                {
                    if (cur.Y > point.Y && Vector.CrossProduct(prev - point, cur - point) > 0)
                        ++winding;
                }
                else
                {
                    if (cur.Y <= point.Y && Vector.CrossProduct(prev - point, cur - point) < 0)
                        --winding;
                }
                prev = cur;
            }

            return winding;
        }
        public ShapeLengthAngleRepresentation(ShapeStructure structure, Vector origin, IEnumerable<double> edgeLengths, IEnumerable<double> edgeAngles, IEnumerable<double> edgeWidths)
        {
            if (edgeLengths == null)
                throw new ArgumentNullException("edgeLengths");
            if (edgeAngles == null)
                throw new ArgumentNullException("edgeAngles");
            if (edgeWidths == null)
                throw new ArgumentNullException("edgeWidths");
            if (structure == null)
                throw new ArgumentNullException("structure");

            this.edgeLengths = new ExposableCollection<double>(edgeLengths.ToList());
            this.edgeAngles = new ExposableCollection<double>(edgeAngles.ToList());
            this.edgeWidths = new ExposableCollection<double>(edgeWidths.ToList());
            this.Structure = structure;
            this.Origin = origin;

            if (this.edgeLengths.Count != this.Structure.Edges.Count)
                throw new ArgumentException("Edge lengths count should be equal to edge count.", "edgeLengths");
            if (this.edgeAngles.Count != this.Structure.Edges.Count)
                throw new ArgumentException("Edge angles count should be equal to edge count.", "edgeAngles");
            if (this.edgeWidths.Count != this.Structure.Edges.Count)
                throw new ArgumentException("Edge widths count should be equal to edge count.", "edgeWidths");
        }
 public static double DotProduct(Vector vector1, Vector vector2)
 {
     return vector1.X * vector2.X + vector1.Y * vector2.Y;
 }
 public void DistanceToLineSquared(Vector point1, Vector point2, out double distanceSqr, out double alpha)
 {
     Vector v = point2 - point1;
     Vector p = this - point1;
     alpha = DotProduct(v, p) / v.LengthSquared;
     distanceSqr = ((point1 + alpha * v) - this).LengthSquared;
 }
 public static double AngleBetween(Vector vector1, Vector vector2)
 {
     if (vector1 == vector2)
         return 0;
     vector1 = vector1.GetNormalized();
     vector2 = vector2.GetNormalized();
     double cos = DotProduct(vector1, vector2);
     double sin = CrossProduct(vector1, vector2);
     double angle = Math.Atan2(sin, cos);
     return angle;
 }
 public double DistanceToLine(Vector point1, Vector point2)
 {
     return Math.Sqrt(this.DistanceToLineSquared(point1, point2));
 }
 public double DistanceToLineSquared(Vector point1, Vector point2)
 {
     double distanceSqr, alpha;
     this.DistanceToLineSquared(point1, point2, out distanceSqr, out alpha);
     return distanceSqr;
 }
        static void LengthAngleDependenceExperiment(
            VertexConstraints constraint1, VertexConstraints constraint2, string fileName)
        {
            const int GeneratedPointCount = 100000;

            List<Vector> lengthAnglePoints = new List<Vector>();
            double maxLength = 0;
            for (int i = 0; i < GeneratedPointCount; ++i)
            {
                double randomX1 = constraint1.MinCoord.X + Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X);
                double randomY1 = constraint1.MinCoord.Y + Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y);
                double randomX2 = constraint2.MinCoord.X + Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X);
                double randomY2 = constraint2.MinCoord.Y + Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y);
                Vector vector1 = new Vector(randomX1, randomY1);
                Vector vector2 = new Vector(randomX2, randomY2);
                if (vector1 == vector2)
                    continue;

                Vector diff = vector2 - vector1;
                double length = diff.Length;
                double angle = Vector.AngleBetween(Vector.UnitX, diff);
                lengthAnglePoints.Add(new Vector(length, angle));

                maxLength = Math.Max(maxLength, length);
            }

            //ShapeConstraints constraintSet = ShapeConstraints.CreateFromConstraints(
            //    CreateSimpleShapeModel1(),
            //    new[] { constraint1, constraint2 },
            //    new[] { new EdgeConstraints(1) },
            //    1,
            //    1);
            BoxSetLengthAngleConstraints lengthAngleConstraints =
                BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 2, 0);

            const int lengthImageSize = 360;
            const int angleImageSize = 360;
            double lengthScale = (lengthImageSize - 20) / maxLength;

            //Image2D<bool> myAwesomeMask = new Image2D<bool>(lengthImageSize, angleImageSize);
            //LengthAngleSpaceSeparatorSet myAwesomeSeparator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2);
            //for (int i = 0; i < lengthImageSize; ++i)
            //    for (int j = 0; j < angleImageSize; ++j)
            //    {
            //        double length = i / lengthScale;
            //        double angle = MathHelper.ToRadians(j - 180.0);
            //        if (myAwesomeSeparator.IsInside(length, angle))
            //            myAwesomeMask[i, j] = true;
            //    }

            using (Bitmap image = new Bitmap(lengthImageSize, angleImageSize))
            using (Graphics graphics = Graphics.FromImage(image))
            {
                graphics.Clear(Color.White);

                // Draw generated points
                for (int i = 0; i < lengthAnglePoints.Count; ++i)
                    DrawLengthAngle(graphics, Pens.Black, lengthAnglePoints[i].X, lengthAnglePoints[i].Y, lengthScale, 1);

                // Draw estimated ranges
                foreach (BoxLengthAngleConstraints child in lengthAngleConstraints.ChildConstraints)
                    DrawLengthAngleConstraintBox(graphics, Pens.Green, child, lengthScale);
                DrawLengthAngleConstraintBox(graphics, new Pen(Color.Red, 2), lengthAngleConstraints.OverallRange, lengthScale);

                // Draw constraint corners
                //for (int i = 0; i < 4; ++i)
                //{
                //    for (int j = 0; j < 4; ++j)
                //    {
                //        Vector diff = constraint2.Corners[j] - constraint1.Corners[i];
                //        DrawLengthAngle(diff.Length, Vector.AngleBetween(Vector.UnitX, diff), lengthScale, 5, graphics, Pens.Blue);
                //    }
                //}

                // Draw my awesome separation lines
                //for (int i = 0; i < lengthImageSize - 1; ++i)
                //    for (int j = 0; j < lengthImageSize - 1; ++j)
                //    {
                //        bool border = false;
                //        border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j];
                //        border |= myAwesomeMask[i, j] != myAwesomeMask[i, j + 1];
                //        border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j + 1];
                //        if (border)
                //            image.SetPixel(i, j, Color.Orange);
                //    }

                //graphics.DrawString(
                //    String.Format("Max length is {0:0.0}", maxLength), SystemFonts.DefaultFont, Brushes.Green, 5, 5);

                image.Save(fileName);
            }
        }
        public void DistanceToSegmentSquared(Vector segmentStart, Vector segmentEnd, out double distanceSqr, out double alpha)
        {
            Vector v = segmentEnd - segmentStart;
            Vector p = this - segmentStart;

            alpha = DotProduct(v, p) / v.LengthSquared;
            if (alpha >= 0 && alpha <= 1)
                distanceSqr = ((segmentStart + alpha * v) - this).LengthSquared;
            else if (alpha < 0)
                distanceSqr = p.LengthSquared;
            else
                distanceSqr = (this - segmentEnd).LengthSquared;
        }
 public bool Contains(Vector vector)
 {
     return
         vector.X >= this.MinCoord.X &&
         vector.Y >= this.MinCoord.Y &&
         vector.X <= this.MaxCoord.X &&
         vector.Y <= this.MaxCoord.Y;
 }
        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);
        }
        private Image DrawConstraintsOnTopOfImage(
            Image backgroundImage, float drawSizeRatio, ShapeConstraints shapeConstraints, bool drawVertexConstraints, bool drawMinEdgeWidth, bool drawMaxEdgeWidth, bool drawAverageEdgeWidth)
        {
            const float pointRadius = 4;
            const float lineWidth   = 2;

            Bitmap statusImage = new Bitmap((int)(backgroundImage.Width * drawSizeRatio), (int)(backgroundImage.Height * drawSizeRatio));

            using (Graphics graphics = Graphics.FromImage(statusImage))
            {
                graphics.DrawImage(backgroundImage, 0, 0, statusImage.Width, statusImage.Height);

                if (drawVertexConstraints)
                {
                    foreach (VertexConstraints vertexConstraint in shapeConstraints.VertexConstraints)
                    {
                        graphics.DrawRectangle(
                            new Pen(Color.Orange, lineWidth),
                            (float)vertexConstraint.MinCoord.X * drawSizeRatio,
                            (float)vertexConstraint.MinCoord.Y * drawSizeRatio,
                            (float)(vertexConstraint.MaxCoord.X - vertexConstraint.MinCoord.X) * drawSizeRatio,
                            (float)(vertexConstraint.MaxCoord.Y - vertexConstraint.MinCoord.Y) * drawSizeRatio);
                    }
                }

                foreach (VertexConstraints vertexConstraint in shapeConstraints.VertexConstraints)
                {
                    graphics.FillEllipse(
                        Brushes.Black,
                        (float)vertexConstraint.MiddleCoord.X * drawSizeRatio - pointRadius,
                        (float)vertexConstraint.MiddleCoord.Y * drawSizeRatio - pointRadius,
                        2 * pointRadius,
                        2 * pointRadius);
                }

                for (int i = 0; i < shapeConstraints.ShapeStructure.Edges.Count; ++i)
                {
                    ShapeEdge edge   = shapeConstraints.ShapeStructure.Edges[i];
                    Vector    point1 = shapeConstraints.VertexConstraints[edge.Index1].MiddleCoord * drawSizeRatio;
                    Vector    point2 = shapeConstraints.VertexConstraints[edge.Index2].MiddleCoord * drawSizeRatio;
                    graphics.DrawLine(new Pen(Color.Black, lineWidth), MathHelper.VecToPointF(point1), MathHelper.VecToPointF(point2));

                    if (drawMinEdgeWidth || drawMaxEdgeWidth || drawAverageEdgeWidth)
                    {
                        EdgeConstraints edgeConstraint = shapeConstraints.EdgeConstraints[i];
                        Vector          diff           = point2 - point1;
                        Vector          edgeNormal     = (new Vector(diff.Y, -diff.X)).GetNormalized();

                        if (drawMaxEdgeWidth)
                        {
                            DrawOrientedRectange(graphics, point1, point2, edgeNormal, (float)edgeConstraint.MaxWidth * drawSizeRatio, new Pen(Color.Cyan, lineWidth));
                        }
                        if (drawMinEdgeWidth)
                        {
                            DrawOrientedRectange(graphics, point1, point2, edgeNormal, (float)edgeConstraint.MinWidth * drawSizeRatio, new Pen(Color.Red, lineWidth));
                        }
                        if (drawAverageEdgeWidth)
                        {
                            DrawOrientedRectange(graphics, point1, point2, edgeNormal, (float)(edgeConstraint.MinWidth + edgeConstraint.MaxWidth) * drawSizeRatio * 0.5f, new Pen(Color.Blue, lineWidth));
                        }
                    }
                }
            }

            return(statusImage);
        }
 public double DistanceToPoint(Vector vector)
 {
     return Math.Sqrt(this.DistanceToPointSquared(vector));
 }
 public static PointF VecToPointF(Vector vec)
 {
     return new PointF((float)vec.X, (float)vec.Y);
 }
 public static Vector Trunc(Vector value, Vector min, Vector max)
 {
     return new Vector(
         Trunc(value.X, min.X, max.X),
         Trunc(value.Y, min.Y, max.Y));
 }
        static void LengthAngleDependenceExperiment(
            VertexConstraints constraint1, VertexConstraints constraint2, string fileName)
        {
            const int GeneratedPointCount = 100000;

            List <Vector> lengthAnglePoints = new List <Vector>();
            double        maxLength         = 0;

            for (int i = 0; i < GeneratedPointCount; ++i)
            {
                double randomX1 = constraint1.MinCoord.X + Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X);
                double randomY1 = constraint1.MinCoord.Y + Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y);
                double randomX2 = constraint2.MinCoord.X + Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X);
                double randomY2 = constraint2.MinCoord.Y + Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y);
                Vector vector1  = new Vector(randomX1, randomY1);
                Vector vector2  = new Vector(randomX2, randomY2);
                if (vector1 == vector2)
                {
                    continue;
                }

                Vector diff   = vector2 - vector1;
                double length = diff.Length;
                double angle  = Vector.AngleBetween(Vector.UnitX, diff);
                lengthAnglePoints.Add(new Vector(length, angle));

                maxLength = Math.Max(maxLength, length);
            }

            //ShapeConstraints constraintSet = ShapeConstraints.CreateFromConstraints(
            //    CreateSimpleShapeModel1(),
            //    new[] { constraint1, constraint2 },
            //    new[] { new EdgeConstraints(1) },
            //    1,
            //    1);
            BoxSetLengthAngleConstraints lengthAngleConstraints =
                BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 2, 0);

            const int lengthImageSize = 360;
            const int angleImageSize  = 360;
            double    lengthScale     = (lengthImageSize - 20) / maxLength;

            //Image2D<bool> myAwesomeMask = new Image2D<bool>(lengthImageSize, angleImageSize);
            //LengthAngleSpaceSeparatorSet myAwesomeSeparator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2);
            //for (int i = 0; i < lengthImageSize; ++i)
            //    for (int j = 0; j < angleImageSize; ++j)
            //    {
            //        double length = i / lengthScale;
            //        double angle = MathHelper.ToRadians(j - 180.0);
            //        if (myAwesomeSeparator.IsInside(length, angle))
            //            myAwesomeMask[i, j] = true;
            //    }

            using (Bitmap image = new Bitmap(lengthImageSize, angleImageSize))
                using (Graphics graphics = Graphics.FromImage(image))
                {
                    graphics.Clear(Color.White);

                    // Draw generated points
                    for (int i = 0; i < lengthAnglePoints.Count; ++i)
                    {
                        DrawLengthAngle(graphics, Pens.Black, lengthAnglePoints[i].X, lengthAnglePoints[i].Y, lengthScale, 1);
                    }

                    // Draw estimated ranges
                    foreach (BoxLengthAngleConstraints child in lengthAngleConstraints.ChildConstraints)
                    {
                        DrawLengthAngleConstraintBox(graphics, Pens.Green, child, lengthScale);
                    }
                    DrawLengthAngleConstraintBox(graphics, new Pen(Color.Red, 2), lengthAngleConstraints.OverallRange, lengthScale);

                    // Draw constraint corners
                    //for (int i = 0; i < 4; ++i)
                    //{
                    //    for (int j = 0; j < 4; ++j)
                    //    {
                    //        Vector diff = constraint2.Corners[j] - constraint1.Corners[i];
                    //        DrawLengthAngle(diff.Length, Vector.AngleBetween(Vector.UnitX, diff), lengthScale, 5, graphics, Pens.Blue);
                    //    }
                    //}

                    // Draw my awesome separation lines
                    //for (int i = 0; i < lengthImageSize - 1; ++i)
                    //    for (int j = 0; j < lengthImageSize - 1; ++j)
                    //    {
                    //        bool border = false;
                    //        border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j];
                    //        border |= myAwesomeMask[i, j] != myAwesomeMask[i, j + 1];
                    //        border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j + 1];
                    //        if (border)
                    //            image.SetPixel(i, j, Color.Orange);
                    //    }

                    //graphics.DrawString(
                    //    String.Format("Max length is {0:0.0}", maxLength), SystemFonts.DefaultFont, Brushes.Green, 5, 5);

                    image.Save(fileName);
                }
        }
 public static double CrossProduct(Vector vector1, Vector vector2)
 {
     return vector1.X * vector2.Y - vector1.Y * vector2.X;
 }
        private void OnShapeCanvasMouseMove(object sender, MouseEventArgs e)
        {
            Point mousePos = e.GetPosition(this.shapeCanvas);
            
            if (this.controlledVertexIndex.HasValue)
            {
                this.shape.VertexPositions[this.controlledVertexIndex.Value] = new Vector(mousePos.X, mousePos.Y) - this.mouseOffset;
            }
            else if (this.controlledEdgeIndex.HasValue)
            {
                ShapeEdge edge = this.shape.Structure.Edges[this.controlledEdgeIndex.Value];
                double distanceFromEdgeLine = new Vector(mousePos.X, mousePos.Y).DistanceToLine(
                    this.shape.VertexPositions[edge.Index1], this.shape.VertexPositions[edge.Index2]);
                this.shape.EdgeWidths[this.controlledEdgeIndex.Value] =
                    Math.Max(this.initialEdgeWidth + 2 * (distanceFromEdgeLine - this.initialDistanceFromEdgeLine), 5);
            }

            if (this.controlledVertexIndex.HasValue || this.controlledEdgeIndex.HasValue)
                this.UpdateShapeControls();
        }
 public double DistanceToPointSquared(Vector vector)
 {
     return (vector - this).LengthSquared;
 }
 /// <summary>
 /// Checks if point is inside the polygon. Polygon is assumed to be "simple".
 /// </summary>
 /// <param name="point">Point to check.</param>
 /// <returns>True if point is inside, false otherwise.</returns>
 public bool IsPointInside(Vector point)
 {
     int windingNumber = this.WindingNumber(point);
     return windingNumber == 1 || windingNumber == -1;
 }
 public double DistanceToSegment(Vector segmentStart, Vector segmentEnd)
 {
     return Math.Sqrt(this.DistanceToSegmentSquared(segmentStart, segmentEnd));
 }
 public void DistanceToSegment(Vector segmentStart, Vector segmentEnd, out double distance, out double alpha)
 {
     double distanceSqr;
     this.DistanceToSegmentSquared(segmentStart, segmentEnd, out distanceSqr, out alpha);
     distance = Math.Sqrt(distanceSqr);
 }
 public VertexConstraints(Vector coord)
     : this(coord, coord)
 {
 }
 public double DistanceToSegmentSquared(Vector segmentStart, Vector segmentEnd)
 {
     double distanceSqr, alpha;
     this.DistanceToSegmentSquared(segmentStart, segmentEnd, out distanceSqr, out alpha);
     return distanceSqr;
 }
        public static Polygon SolvePulleyProblem(Circle circle1, Circle circle2)
        {
            if (circle1.Radius < circle2.Radius)
                Helper.Swap(ref circle1, ref circle2);

            Debug.Assert(!circle1.Contains(circle2));

            double edgeLength = (circle1.Center - circle2.Center).Length;
            double cosAngle = (circle1.Radius - circle2.Radius) / edgeLength;
            double angle = Math.Acos(cosAngle);
            Debug.Assert(angle >= 0 && angle <= Math.PI / 2);

            double lineAngle = Math.Atan2(circle2.Center.Y - circle1.Center.Y, circle2.Center.X - circle1.Center.X);
            double cosPlusPlus = Math.Cos(lineAngle + angle);
            double sinPlusPlus = Math.Sin(lineAngle + angle);
            double cosPlusMinus = Math.Cos(lineAngle - angle);
            double sinPlusMinus = Math.Sin(lineAngle - angle);

            Vector line1Point1 = new Vector(
                circle1.Center.X + circle1.Radius * cosPlusPlus,
                circle1.Center.Y + circle1.Radius * sinPlusPlus);
            Vector line2Point1 = new Vector(
                circle1.Center.X + circle1.Radius * cosPlusMinus,
                circle1.Center.Y + circle1.Radius * sinPlusMinus);
            Vector line1Point2 = new Vector(
                circle2.Center.X + circle2.Radius * cosPlusPlus,
                circle2.Center.Y + circle2.Radius * sinPlusPlus);
            Vector line2Point2 = new Vector(
                circle2.Center.X + circle2.Radius * cosPlusMinus,
                circle2.Center.Y + circle2.Radius * sinPlusMinus);

            return Polygon.FromPoints(line1Point1, line1Point2, line2Point2, line2Point1);
        }
 private void DrawOrientedRectange(Graphics graphics, Vector point1, Vector point2, Vector sideDirection, float sideWidth, Pen pen)
 {
     graphics.DrawPolygon(
         pen,
         new[]
     {
         MathHelper.VecToPointF(point1 - sideDirection * sideWidth * 0.5),
         MathHelper.VecToPointF(point1 + sideDirection * sideWidth * 0.5),
         MathHelper.VecToPointF(point2 + sideDirection * sideWidth * 0.5),
         MathHelper.VecToPointF(point2 - sideDirection * sideWidth * 0.5)
     });
 }