コード例 #1
0
        public void CanDetectConnectedAndNotConnectedAtReentrantAngle()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are coincident
            AddFeature(fcBorder1,
                       CurveConstruction.StartLine(10, 100)
                       .LineTo(0, 0)
                       .LineTo(0, -2)
                       .LineTo(100, -2)
                       .Curve, stateId: "A");
            AddFeature(fcBorder2,
                       CurveConstruction.StartLine(100, -2)
                       .LineTo(0, -2)
                       .LineTo(0, 0)
                       .LineTo(10, 100)
                       .Curve, stateId: "B");

            // connected to border:
            AddFeature(fcArea1,
                       CurveConstruction.StartPoly(10, 100)
                       .LineTo(0, 0)
                       .LineTo(-10, 0)
                       .LineTo(-10, 100)
                       .ClosePolygon(), stateId: "A");
            AddFeature(fcArea1,
                       CurveConstruction.StartPoly(0, 0)
                       .LineTo(0, -2)
                       .LineTo(100, -2)
                       .LineTo(100, -10)
                       .LineTo(-10, -10)
                       .LineTo(-10, 0)
                       .ClosePolygon(), stateId: "A");

            AddAreaFeature(fcArea2, 0, -2, 100, 0, stateId: "B");             // connected
            AddFeature(fcArea2,
                       CurveConstruction.StartPoly(0.5, 5)
                       .LineTo(50, 50)
                       .Line(50, 100)
                       .LineTo(10, 100)
                       .ClosePolygon(), stateId: "B");                              // connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 10,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            AssertUtils.ExpectedErrors(1, Run(test, 1000));
        }
コード例 #2
0
        public void CanIgnoreNotConnectedWithBoundingFeature()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;
            int           ticks = CreateFeatureClasses(out fcArea1, out fcArea2,
                                                       out fcBorder1, out fcBorder2);

            IFeatureClass boundingLineClass  = CreateLineClass(string.Format("el1_{0}", ticks));
            IFeatureClass boundingPointClass =
                CreateFeatureClass(string.Format("ep1_{0}", ticks),
                                   esriGeometryType.esriGeometryPoint);

            // border lines are coincident
            AddLineFeature(fcBorder1, 0, 0, 100, 0, stateId: "A");
            AddLineFeature(fcBorder2, 100, 0, 0, 0, stateId: "B");

            // connected to border:
            AddAreaFeature(fcArea1, 10, 0, 90, 5, stateId: "A");
            AddAreaFeature(fcArea2, 20, -5, 40, 0, stateId: "B");           // connected
            AddAreaFeature(fcArea2, 60, -5, 80, 0, stateId: "B");           // connected
            AddAreaFeature(fcArea2, 0, -5, 8, 0, stateId: "B");             // not connected

            AddLineFeature(boundingLineClass, 12, 0, 16, 0);
            AddFeature(boundingPointClass, GeometryFactory.CreatePoint(85, 0));
            AddFeature(boundingPointClass, GeometryFactory.CreatePoint(4, 0));

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    0.5,
                                                    new[]
            {
                boundingLineClass,
                boundingPointClass
            },
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            // fcArea1: 40-60: missing
            // fcArea2: 0 - 8: missing
            var expectedErrors =
                new Predicate <QaError>[]
            {
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 8) &&
                HasEnvelope(e, xmin: 0, xmax: 8),
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 20) &&
                HasEnvelope(e, xmin: 40, xmax: 60)
            };

            AssertUtils.ExpectedErrors(2, Run(test, 1000), expectedErrors);

            AssertUtils.ExpectedErrors(2, Run(test, 1000), expectedErrors);
        }
コード例 #3
0
        public void CanIgnoreConnectedFeatures()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are coincident
            AddLineFeature(fcBorder1, 0, 0, 10, 0, stateId: "A");
            AddLineFeature(fcBorder2, 10, 0, 0, 0, stateId: "B");

            // connected to border:
            AddAreaFeature(fcArea1, 5, 0, 7, 5, stateId: "A");
            // connected to border, exact match:
            AddAreaFeature(fcArea2, 5, -5, 7, 0, stateId: "B");

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 0.5,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            AssertNoErrors(Run(test, 1000));

            AssertNoErrors(Run(test, 5));
        }
コード例 #4
0
        public void CanDetectNotConnectedAndBorderGap()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are not coincident
            AddLineFeature(fcBorder1, 0, 0, 10, 0, stateId: "A");
            AddLineFeature(fcBorder2, 10, -0.3, 0, -0.3, stateId: "B");

            AddAreaFeature(fcArea1, 5, 0, 8, 5, stateId: "A");             // connected
            AddAreaFeature(fcArea2, 4, -5, 7, -0.3, stateId: "B");         // connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 0.5,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            var expectedErrors =
                new Predicate <QaError>[]
            {
                // TODO currently fails, revise subtraction of buffer from remainder:
                // When search distance is large compared to offset between borders, error
                // geometry of "NoCandidate" is significantly reduced, to the point that
                // it can become empty
                // (expected values may have to be adapted, maybe not achievable as defined below)
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 1) &&
                HasEnvelope(e, 4, -0.3, 5, -0.3),
                e =>
                HasCode(
                    e, "NoMatch.CandidateExists.BordersNotCoincident.ConstraintsFulfilled") &&
                HasLength(e, 2 + 2) &&
                HasEnvelope(e, 5, -0.3, xmax: 7, ymax: 0),
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 1) &&
                HasEnvelope(e, xmin: 7, ymin: 0, xmax: 8, ymax: 0)
            };

            AssertUtils.ExpectedErrors(3, Run(test, 1000), expectedErrors);

            AssertUtils.ExpectedErrors(3, Run(test, 5), expectedErrors);
        }
コード例 #5
0
        public void CheckAreErrorsIndependentOnFeatureOrder()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2,
                                 out fcBorder1, out fcBorder2);

            var border11 =
                (IPolyline)CurveConstruction.StartLine(40, 60).LineTo(0, 50).Curve;
            var border12 =
                (IPolyline)CurveConstruction.StartLine(0, 50).LineTo(200, 0).Curve;

            var border21 =
                (IPolyline)CurveConstruction.StartLine(40, 60.01).LineTo(0, 50.01).Curve;
            var border22 =
                (IPolyline)CurveConstruction.StartLine(0, 50.01).LineTo(200, 0.01).Curve;

            // connected to border:
            IPolygon area11 = CurveConstruction.StartPoly(40, 60).LineTo(0, 50).LineTo(200, 0)
                              .ClosePolygon();

            IPolygon area21 =
                CurveConstruction.StartPoly(40, 60.01).LineTo(0, 50.01).LineTo(-100, 50)
                .ClosePolygon();

            IPolygon area22 =
                CurveConstruction.StartPoly(0, 50.01).LineTo(200, 0.01).LineTo(100, -50)
                .ClosePolygon();

            QaEdgeMatchCrossingAreas test = CreateTest(new[] { area22, area21 },
                                                       new[] { border21, border22 },
                                                       new[] { area11 },
                                                       new[] { border11, border12 });

            var errors1 = new List <QaError>(Run(test, 1000));

            test = CreateTest(new[] { area11 }, new[] { border11, border12 },
                              new[] { area21, area22 }, new[] { border21, border22 });

            var errors2 = new List <QaError>(Run(test, 1000));

            Assert.AreEqual(errors1.Count, errors2.Count);
            // TODO : Compare Errors
        }
コード例 #6
0
        public void CanDetectBorderGapBackslashed()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are not coincident
            AddLineFeature(fcBorder1, -2, 2, 1, -2, stateId: "A");
            AddLineFeature(fcBorder2, 1.01, -2, -1.99, 2, stateId: "B");

            AddFeature(fcArea1,
                       CurveConstruction.StartPoly(-2, 2)
                       .LineTo(1, -2)
                       .LineTo(-5, -10)
                       .ClosePolygon(), stateId: "A");                              // connected
            AddFeature(fcArea2,
                       CurveConstruction.StartPoly(1.01, -2)
                       .LineTo(-1.99, 2)
                       .LineTo(5, 10)
                       .ClosePolygon(), stateId: "B");                              // connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 0.2,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            AssertUtils.ExpectedErrors(3, Run(test, 1000));

            AssertUtils.ExpectedErrors(3, Run(test, 1));

            var runner = new QaContainerTestRunner(1, test)
            {
                KeepGeometry = true
            };

            runner.Execute(GeometryFactory.CreateEnvelope(-9, -4, 9, 8));
            AssertUtils.ExpectedErrors(3, runner.Errors);
        }
コード例 #7
0
        public void CanIgnoreConnectedFeaturesAtOppositeSplitBorderInEdge()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are coincident BUT with a split at opposite side of area split!!
            AddLineFeature(fcBorder1, 0, 0, 5, 0, stateId: "A");             // split point at x=5
            AddLineFeature(fcBorder1, 5, 0, 0, -5, stateId: "A");

            AddFeature(fcBorder2,
                       CurveConstruction.StartLine(0, -5).LineTo(5, 0).LineTo(0, 0).Curve,
                       stateId: "B");

            // connected to split border, one polygon
            AddFeature(fcArea1,
                       CurveConstruction.StartPoly(2, 0)
                       .LineTo(5, 0)
                       .LineTo(2, -3)
                       .ClosePolygon(), stateId: "A");

            // two polygons connected to non-split border
            AddAreaFeature(fcArea2, 2, 0, 5, 100, stateId: "B");             // split point at x=5
            AddFeature(fcArea2,
                       CurveConstruction.StartPoly(2, -3)
                       .LineTo(5, 0)
                       .LineTo(5, -3)
                       .ClosePolygon(), stateId: "B");

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 1,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            AssertNoErrors(Run(test, 1000));

            AssertNoErrors(Run(test, 5));
        }
コード例 #8
0
        public void CanDetectConnectedAndMissing()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are coincident
            AddLineFeature(fcBorder1, 0, 0, 100, 0, stateId: "A");
            AddLineFeature(fcBorder2, 100, 0, 0, 0, stateId: "B");

            // connected to border:
            AddAreaFeature(fcArea1, 10, 0, 90, 5, stateId: "A");

            AddAreaFeature(fcArea2, 15, -5, 30, 0, stateId: "B");             // connected
            AddAreaFeature(fcArea2, 30, -5, 50, 0, stateId: "B");             // connected
            AddAreaFeature(fcArea2, 50, -5, 80, 0, stateId: "B");             // connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 0.5,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            var expectedErrors =
                new Predicate <QaError>[]
            {
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 10) &&
                HasEnvelope(e, xmin: 80, xmax: 90),
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 5) &&
                HasEnvelope(e, xmin: 10, xmax: 15)
            };

            AssertUtils.ExpectedErrors(2, Run(test, 1000), expectedErrors);

            AssertUtils.ExpectedErrors(2, Run(test, 10), expectedErrors);
        }
コード例 #9
0
        CanIgnoreWhenAllowDisjointCandidateFeatureIfAttributeConstraintsAreFulfilled()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2,
                                 out fcBorder1, out fcBorder2);

            // border lines are coincident
            AddLineFeature(fcBorder1, 0, 0, 100, 0, stateId: "A");
            AddLineFeature(fcBorder2, 100, -0.1, 0, -0.1, stateId: "B");

            // connected to border:
            AddAreaFeature(fcArea1, 10, 0, 30, 5, stateId: "A", textFieldValue: "Y");
            AddAreaFeature(fcArea1, 30, 0, 70, 5, stateId: "A", textFieldValue: "Y");
            AddAreaFeature(fcArea1, 70, 0, 90, 5, stateId: "A", textFieldValue: "Y");
            AddAreaFeature(fcArea2, 10, -5, 15, -0.1, stateId: "B", textFieldValue: "Y");
            // not connected
            AddAreaFeature(fcArea2, 15, -5, 50, -0.1, stateId: "B", textFieldValue: "Y");
            // not connected
            AddAreaFeature(fcArea2, 50, -5, 55, -0.1, stateId: "B", textFieldValue: "Y");
            // not connected
            AddAreaFeature(fcArea2, 55, -5, 90, -0.1, stateId: "B", textFieldValue: "Y");
            // not connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    0.5,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE",
                CrossingAreaEqualAttributes    = "FLD_TEXT",
                AllowDisjointCandidateFeatureIfAttributeConstraintsAreFulfilled = true
            };

            AssertUtils.ExpectedErrors(0, Run(test, 1000));

            AssertUtils.ExpectedErrors(0, Run(test, 2));
        }
コード例 #10
0
        CreateTest(IEnumerable <IPolygon> areas1, IEnumerable <IPolyline> borders1,
                   IEnumerable <IPolygon> areas2, IEnumerable <IPolyline> borders2)
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2,
                                 out fcBorder1, out fcBorder2);

            foreach (IPolygon area in areas1)
            {
                AddFeature(fcArea1, area, stateId: "A");
            }

            foreach (IPolyline border in borders1)
            {
                AddFeature(fcBorder1, border, stateId: "A");
            }

            foreach (IPolygon area in areas2)
            {
                AddFeature(fcArea2, area, stateId: "B");
            }

            foreach (IPolyline border in borders2)
            {
                AddFeature(fcBorder2, border, stateId: "B");
            }

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    10, null, null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            return(test);
        }
コード例 #11
0
        public void CanDetectBorderGapVertical()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are not coincident
            AddLineFeature(fcBorder1, 0, 0, 0, 10, stateId: "A");
            AddLineFeature(fcBorder1, 0.7, -0.3, 10, -0.3, stateId: "A");
            AddLineFeature(fcBorder2, 0.3, 10, 0.3, 0, stateId: "B");
            AddLineFeature(fcBorder2, 10, 0, 0.7, 0, stateId: "B");

            AddAreaFeature(fcArea1, -10, 0, 0, 10, stateId: "A");             // connected
            AddAreaFeature(fcArea1, 0.7, -5, 10, -0.3, stateId: "A");         // connected
            AddAreaFeature(fcArea2, 0.3, 0, 10, 10, stateId: "B");            // connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 0.5,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            AssertUtils.ExpectedErrors(2, Run(test, 1000));

            AssertUtils.ExpectedErrors(2, Run(test, 3));

            var runner = new QaContainerTestRunner(3, test)
            {
                KeepGeometry = true
            };

            runner.Execute(GeometryFactory.CreateEnvelope(-9, -4, 9, 8));
            AssertUtils.ExpectedErrors(2, runner.Errors);
        }
コード例 #12
0
        public void CanDetectConnectedAndNotConnected()
        {
            IFeatureClass fcArea1;
            IFeatureClass fcArea2;
            IFeatureClass fcBorder1;
            IFeatureClass fcBorder2;

            CreateFeatureClasses(out fcArea1, out fcArea2, out fcBorder1, out fcBorder2);

            // border lines are coincident
            AddLineFeature(fcBorder1, 0, 0, 100, 0, stateId: "A");
            AddLineFeature(fcBorder2, 40, 0, 0, 0, stateId: "B");
            AddFeature(fcBorder2,
                       CurveConstruction.StartLine(100, 0.2)
                       .LineTo(50, 0.2)
                       .LineTo(50, 0)
                       .LineTo(40, 0)
                       .Curve,
                       stateId: "B");

            // connected to border:
            AddAreaFeature(fcArea1, 10, 0, 90, 5, stateId: "A");

            AddAreaFeature(fcArea2, 15, -5, 30, 0, stateId: "B");             // connected
            AddAreaFeature(fcArea2, 30, -5, 50, 0, stateId: "B");             // connected
            AddAreaFeature(fcArea2, 50, -5, 80, 0.2, stateId: "B");           // not connected

            var test = new QaEdgeMatchCrossingAreas(fcArea1, fcBorder1,
                                                    fcArea2, fcBorder2,
                                                    searchDistance: 0.5,
                                                    boundingClasses1: null,
                                                    boundingClasses2: null)
            {
                AreaClass1BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                AreaClass2BorderMatchCondition = "AREA.STATE = BORDER.STATE",
                CrossingAreaMatchCondition     = "AREA1.STATE <> AREA2.STATE"
            };

            // 10-15: missing
            // 50-80: not coincident
            // 80-90: missing
            // TODO currently fails, revise subtraction of buffer from remainder:
            // When search distance is large compared to offset between borders, error
            // geometry of "NoCandidate" is significantly reduced, to the point that
            // it can become empty.
            // (expected values may have to be adapted, maybe not achievable as defined below)
            var expectedErrors =
                new Predicate <QaError>[]
            {
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 5) &&
                HasEnvelope(e, xmin: 10, xmax: 15),
                e =>
                HasCode(
                    e, "NoMatch.CandidateExists.BordersNotCoincident.ConstraintsFulfilled") &&
                HasLength(e, 30 + 30.2 + 0.5) &&
                HasEnvelope(e, xmin: 49.5, xmax: 80, ymax: 0.2),
                e => HasCode(e, "NoMatch.NoCandidate") &&
                HasLength(e, 10) &&
                HasEnvelope(e, xmin: 80, xmax: 90)
            };

            AssertUtils.ExpectedErrors(3, Run(test, 1000), expectedErrors);

            AssertUtils.ExpectedErrors(3, Run(test, 10), expectedErrors);
        }