/// <summary> /// Initializes a new instance of the <see cref="MetapostDrawer"/> class. /// </summary> /// <param name="settings"><inheritdoc cref="_settings" path="/summary"/></param> /// <param name="data"><inheritdoc cref="_data" path="/summary"/></param> /// <param name="constructor"><inheritdoc cref="_constructor" path="/summary"/></param> /// <param name="verifier"><inheritdoc cref="_verifier" path="/summary"/></param> public MetapostDrawer(MetapostDrawerSettings settings, MetapostDrawerData data, IGeometryConstructor constructor, IGeometricTheoremVerifier verifier) { _settings = settings ?? throw new ArgumentNullException(nameof(settings)); _data = data ?? throw new ArgumentNullException(nameof(data)); _constructor = constructor ?? throw new ArgumentNullException(nameof(constructor)); _verifier = verifier ?? throw new ArgumentNullException(nameof(verifier)); }
/// <summary> /// Initializes a new instance of the <see cref="ProblemGenerator"/> class. /// </summary> /// <param name="settings">The settings for the problem generator.</param> /// <param name="generator">The generator of configurations.</param> /// <param name="constructor">The constructor that perform geometric construction of configurations.</param> /// <param name="finder">The finder of theorems in generated configurations.</param> /// <param name="tracer">The tracer of potential geometry failures.</param> public ProblemGenerator(ProblemGeneratorSettings settings, IConfigurationGenerator generator, IGeometryConstructor constructor, ITheoremFinder finder, IGeometryFailureTracer tracer) { _settings = settings ?? throw new ArgumentNullException(nameof(settings)); _generator = generator ?? throw new ArgumentNullException(nameof(generator)); _constructor = constructor ?? throw new ArgumentNullException(nameof(constructor)); _finder = finder ?? throw new ArgumentNullException(nameof(finder)); _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); }
/// <summary> /// Initializes a new instance of the <see cref="TrivialTheoremProducer"/> class. /// </summary> /// <param name="constructor">The constructor used to construct underlying configurations of composed constructions.</param> /// <param name="finder">The theorem finder used to determine theorems of composed constructions.</param> public TrivialTheoremProducer(IGeometryConstructor constructor, ITheoremFinder finder) { _constructor = constructor ?? throw new ArgumentNullException(nameof(constructor)); _finder = finder ?? throw new ArgumentNullException(nameof(finder)); }
/// <summary> /// Initializes a new instance of the <see cref="GeometricTheoremVerifier"/> class. /// </summary> /// <param name="constructor">The constructor used for construction of unknown objects of theorems.</param> public GeometricTheoremVerifier(IGeometryConstructor constructor) { _constructor = constructor ?? throw new ArgumentNullException(nameof(constructor)); }
/// <summary> /// Constructs a given <see cref="Configuration"/> to a given number of pictures, using the /// loose object drawing that is in some cases more flexible than the drawing from the method /// <see cref="LooseObjectLayoutDrawing.ConstructUniformLayout(LooseObjectLayout)"/>. These cases /// are two: Triangle, when <see cref="RandomLayoutsHelpers.ConstructNiceAcuteTriangle"/> is used, /// and Quadrilateral, when <see cref="RandomLayoutsHelpers.ConstructRandomConvexQuadrilateralWithHorizontalSide"/> /// or <see cref="RandomLayoutsHelpers.ConstructRandomConvexQuadrilateralWithHorizontalDiagonal"/> /// if the picture is symmetric in such a way that it would look better with a horizontal diagonal, /// or <see cref="RandomLayoutsHelpers.ConstructRandomConvexQuadrilateralWithHorizontalSide"/> otherwise. /// </summary> /// <param name="configuration">The configuration to be constructed.</param> /// <param name="theorem">The theorem that is used to determine symmetry be constructed.</param> /// <param name="numberOfPictures">The number of <see cref="Picture"/>s where the configuration should be drawn.</param> /// <returns>The tuple consisting of the pictures and the construction data.</returns> /// <exception cref="ConstructorException">Thrown when the construction couldn't be carried out correctly.</exception> public static PicturesOfConfiguration ConstructWithFlexibleLayoutRespectingSymmetry(this IGeometryConstructor constructor, Configuration configuration, Theorem theorem, int numberOfPictures) { #region Loose object layout construction // Prepare the function that will construct the loose objects IAnalyticObject[] LooseObjectsConstructor() { // The layout is drawn based on its type switch (configuration.LooseObjectsHolder.Layout) { // We want to draw less uniform triangles case LooseObjectLayout.Triangle: { // Create the points var(point1, point2, point3) = RandomLayoutsHelpers.ConstructNiceAcuteTriangle(); // Return them in an array return(new IAnalyticObject[] { point1, point2, point3 }); } // In quadrilateral cases we need to have a look at its symmetry case LooseObjectLayout.Quadrilateral: { // Assume we're drawing a quadrilateral ABCD var A = configuration.LooseObjects[0]; var B = configuration.LooseObjects[1]; var C = configuration.LooseObjects[2]; var D = configuration.LooseObjects[3]; // We will use a simple local function that checks whether a mapping is symmetric bool IsSymmetric(IReadOnlyDictionary <LooseConfigurationObject, LooseConfigurationObject> mapping) // Take the real mappings => theorem.GetSymmetryMappings(configuration) // And have a look whether any behaves as our .Any(symmetryMapping => mapping.All(pair => symmetryMapping[pair.Key].Equals(pair.Value))); // Find out if the mapping for when the diagonal BD is horizontal is symmetric. // In that case, we need to exchange B and D var canDiagonalBeHorizontal = IsSymmetric(new Dictionary <LooseConfigurationObject, LooseConfigurationObject> { { A, A }, { B, D }, { C, C }, { D, B } }); // Find out if the mapping for when the side AB is horizontal is symmetric. // In that case, we need to exchange A, B and also C, D var canSideBeHorizontal = IsSymmetric(new Dictionary <LooseConfigurationObject, LooseConfigurationObject> { { A, B }, { B, A }, { C, D }, { D, C } }); // We will want to have horizontal mapping preferably, i.e. if it is possible or the diagonal is not if (canSideBeHorizontal || !canDiagonalBeHorizontal) { // Construct the layout var(point1, point2, point3, point4) = RandomLayoutsHelpers.ConstructRandomConvexQuadrilateralWithHorizontalSide(); // Return the points in an array return(new IAnalyticObject[] { point1, point2, point3, point4 }); } // Otherwise the side cannot be horizontal, but at least the diagonal can be else { // Construct the layout var(point1, point2, point3, point4) = RandomLayoutsHelpers.ConstructRandomConvexQuadrilateralWithHorizontalDiagonal(); // Return the points in an array return(new IAnalyticObject[] { point1, point2, point3, point4 }); } } // By default fall-back to the default uniform layout default: return(LooseObjectLayoutDrawing.ConstructUniformLayout(configuration.LooseObjectsHolder.Layout)); } } #endregion try { // Try to construct the configuration where the passed theorem holds using our custom layout drawer var(pictures, constructionData) = constructor.Construct(configuration, numberOfPictures, LooseObjectsConstructor); // Make sure there is no inconstructible object if (constructionData.InconstructibleObject != default) { throw new ConstructionException("The configuration cannot be constructed, because it contains an inconstructible object."); } // Make sure there are no duplicates if (constructionData.Duplicates != default) { throw new ConstructionException("The configuration cannot be constructed, because it contains duplicate objects"); } // If everything is correct, return the pictures return(pictures); } catch (InconsistentPicturesException e) { // If there is an inconsistency problem, re-throw it with a better exception throw new ConstructionException("Construction of the configuration failed due to inconsistencies.", e); } }
/// <summary> /// Constructs a given <see cref="Configuration"/> to a given number of pictures, using the /// loose object drawing from the class <see cref="LooseObjectLayoutDrawing.ConstructUniformLayout(LooseObjectLayout)"/>. /// Throws an <see cref="InconsistentPicturesException"/> if the construction couldn't be carried out consistently. /// </summary> /// <param name="configuration">The configuration to be constructed.</param> /// <param name="numberOfPictures">The number of <see cref="Picture"/>s where the configuration should be drawn.</param> /// <returns>The tuple consisting of the pictures and the construction data.</returns> public static (PicturesOfConfiguration pictures, ConstructionData data) ConstructWithUniformLayout(this IGeometryConstructor constructor, Configuration configuration, int numberOfPictures) // Call the drawing function that uses a custom loose object drawer => constructor.Construct(configuration, numberOfPictures, () => LooseObjectLayoutDrawing.ConstructUniformLayout(configuration.LooseObjectsHolder.Layout));