Exemplo n.º 1
0
        /// <inheritdoc/>
        protected override IAnalyticObject Construct(IAnalyticObject[] input)
        {
            // Get the points
            var A = (Point)input[0];
            var B = (Point)input[1];
            var C = (Point)input[2];

            // If the points are collinear, the construction can't be done
            if (AnalyticHelpers.AreCollinear(A, B, C))
            {
                return(null);
            }

            // Otherwise construct the circumcircle
            return(new Circle(A, B, C));
        }
Exemplo n.º 2
0
        /// <inheritdoc/>
        protected override IAnalyticObject Construct(IAnalyticObject[] input)
        {
            // Get the points
            var A = (Point)input[0];
            var B = (Point)input[1];
            var C = (Point)input[2];

            // If they are collinear, don't perform the construction
            // (it would be possible, but it would be unnecessarily
            // equivalent to the perpendicular line construction)
            if (AnalyticHelpers.AreCollinear(A, B, C))
            {
                return(null);
            }

            // Otherwise construct the result
            return(AnalyticHelpers.InternalAngleBisector(A, B, C));
        }
Exemplo n.º 3
0
        /// <inheritdoc/>
        protected override IAnalyticObject Construct(IAnalyticObject[] input)
        {
            // Pull the points
            var A = (Point)input[0];
            var B = (Point)input[1];
            var C = (Point)input[2];
            var D = (Point)input[3];

            // Make sure A, C, D makes a circle according to the definition of the construction
            if (AnalyticHelpers.AreCollinear(A, C, D))
            {
                return(null);
            }

            // Now we can create the circle
            var circleACD = new Circle(A, C, D);

            // Create the line
            var lineAB = new Line(A, B);

            // Let's intersect them and take the intersection different from the common point
            var intersections = circleACD.IntersectWith(lineAB).Where(intersection => intersection != A).ToArray();

            // If there is no such intersection, then the line is probably tangent to this circle
            if (intersections.Length == 0)
            {
                return(null);
            }

            // If there are two such intersections, then the precision system has really failed...
            if (intersections.Length == 2)
            {
                return(null);
            }

            // Otherwise we can take the only intersection as the result
            return(intersections[0]);
        }
Exemplo n.º 4
0
        /// <inheritdoc/>
        protected override IAnalyticObject Construct(IAnalyticObject[] input)
        {
            // Pull the points
            var A = (Point)input[0];
            var B = (Point)input[1];
            var C = (Point)input[2];
            var D = (Point)input[3];
            var E = (Point)input[4];

            // Make sure the points that should make circles are not collinear
            if (AnalyticHelpers.AreCollinear(A, B, C) || AnalyticHelpers.AreCollinear(A, D, E))
            {
                return(null);
            }

            // Now we can create the circles
            var circleABC = new Circle(A, B, C);
            var circleADE = new Circle(A, D, E);

            // Let's intersect them and take the intersection different from the common point
            var intersections = circleABC.IntersectWith(circleADE).Where(intersection => intersection != A).ToArray();

            // If there is no such intersection, then the circles are probably tangent
            if (intersections.Length == 0)
            {
                return(null);
            }

            // If there are two intersection, then the precision system has really failed...
            if (intersections.Length == 2)
            {
                return(null);
            }

            // Otherwise we can take the only intersection as the result
            return(intersections[0]);
        }
Exemplo n.º 5
0
        /// <inheritdoc/>
        protected override IAnalyticObject Construct(IAnalyticObject[] input)
        {
            #region Verify layout

            // First we need to verify that the objects match the layout
            switch (_construction.Configuration.LooseObjectsHolder.Layout)
            {
            // Two points should be always fine
            case LooseObjectLayout.LineSegment:
                break;

            // Make sure the points are not collinear
            case LooseObjectLayout.Triangle:

                // If yes, the construction shouldn't be possible
                if (AnalyticHelpers.AreCollinear((Point)input[0], (Point)input[1], (Point)input[2]))
                {
                    return(null);
                }

                break;

            // Make sure no three points are collinear
            case LooseObjectLayout.Quadrilateral:

                // Get the points
                var point1 = (Point)input[0];
                var point2 = (Point)input[1];
                var point3 = (Point)input[2];
                var point4 = (Point)input[3];

                // Verify any three of them
                if (AnalyticHelpers.AreCollinear(point1, point2, point3) ||
                    AnalyticHelpers.AreCollinear(point1, point2, point4) ||
                    AnalyticHelpers.AreCollinear(point1, point3, point4) ||
                    AnalyticHelpers.AreCollinear(point2, point3, point4))
                {
                    // If some three are collinear, the construction shouldn't be possible
                    return(null);
                }

                break;

            // Make sure the point doesn't lie on the line
            case LooseObjectLayout.LineAndPoint:

                // If yes, the construction shouldn't be possible
                if (((Line)input[0]).Contains((Point)input[1]))
                {
                    return(null);
                }

                break;

            // Make sure neither of the points lies on the line
            case LooseObjectLayout.LineAndTwoPoints:

                // Get the line
                var line = (Line)input[0];

                // If at least one point lies on the line, the construction
                // shouldn't be possible
                if (line.Contains((Point)input[1]) || line.Contains((Point)input[2]))
                {
                    return(null);
                }

                break;

            // Unhandled cases
            default:
                throw new ConstructorException($"Unhandled value of {nameof(LooseObjectLayout)}: {_construction.Configuration.LooseObjectsHolder.Layout}");
            }

            #endregion

            // Initialize an internal picture in which we're going to construct
            // the configuration that defines our composed construction
            var internalPicture = new Picture();

            // Add the loose objects to the picture
            _construction.Configuration.LooseObjects.Zip(input).ForEach(pair =>
            {
                // Safely try to add them
                internalPicture.TryAdd(pair.First, pair.Second, out var equalObject);

                // If there is an equal object, then we have a weird problem
                if (equalObject != default)
                {
                    throw new ConstructorException("The input for a composed construction doesn't contain distinct objects! This must be a bug...");
                }
            });

            // Add the constructed objects as well
            foreach (var constructedObject in _construction.Configuration.ConstructedObjects)
            {
                // For each one find the construction function
                var constructorFunction = _constructionResolver.Resolve(constructedObject.Construction).Construct(constructedObject);

                // Perform the construction
                var analyticObject = constructorFunction(internalPicture);

                // If it's not constructible, we can't do more
                if (analyticObject == null)
                {
                    return(null);
                }

                // Otherwise add the object to the picture
                internalPicture.TryAdd(constructedObject, analyticObject, out var equalObject);

                // If there is an equal object, we say the construction is incorrect as well
                if (equalObject != null)
                {
                    return(null);
                }
            }

            // If we are here, then the construction should be fine and the result
            // will be in the internal picture corresponding to the last object
            // of the configuration that defines our composed construction
            return(internalPicture.Get(_construction.Configuration.LastConstructedObject));
        }