public static string GetKey(
            [NotNull] IEnumerable <InvolvedRow> involvedRows,
            [CanBeNull] Predicate <string> excludeTableFromKey = null)
        {
            var sb = new StringBuilder();

            IDictionary <string, List <InvolvedRow> > rowsByTableName =
                InvolvedRowUtils.GroupByTableName(involvedRows);

            foreach (
                KeyValuePair <string, List <InvolvedRow> > pair in
                rowsByTableName.OrderBy(p => p.Key))
            {
                string tableName = pair.Key.Trim();

                if (excludeTableFromKey != null && excludeTableFromKey(tableName))
                {
                    continue;
                }

                sb.Append(tableName);
                foreach (int oid in pair.Value.Where(r => r.OID >= 0)
                         .OrderBy(r => r.OID)
                         .Select(r => r.OID))
                {
                    sb.AppendFormat(_oidFormat, oid);
                }

                sb.Append(_tableDelimiter);
            }

            return(sb.ToString());
        }
Esempio n. 2
0
        public static IEnumerable <InvolvedTable> GetInvolvedTables(
            [NotNull] IEnumerable <InvolvedRow> involvedRows)
        {
            var result = new List <InvolvedTable>();

            IEnumerable <KeyValuePair <string, List <InvolvedRow> > > rowsByTableName =
                InvolvedRowUtils.GroupByTableName(involvedRows);

            foreach (KeyValuePair <string, List <InvolvedRow> > pair in rowsByTableName)
            {
                List <InvolvedRow> involvedRowsForTable = pair.Value;
                var rowReferences = new List <RowReference>(involvedRowsForTable.Count);

                foreach (InvolvedRow involvedRow in involvedRowsForTable)
                {
                    if (!involvedRow.RepresentsEntireTable)
                    {
                        rowReferences.Add(new OIDRowReference(involvedRow.OID));
                    }
                }

                result.Add(new InvolvedTable(pair.Key, rowReferences));
            }

            return(result);
        }
Esempio n. 3
0
        private IEnumerable <InvolvedTable> GetInvolvedTables(
            [NotNull] IEnumerable <InvolvedRow> involvedRows,
            [NotNull] QualitySpecificationElement element)
        {
            var result = new List <InvolvedTable>();

            foreach (KeyValuePair <string, List <InvolvedRow> > tableRows in
                     InvolvedRowUtils.GroupByTableName(involvedRows))
            {
                string             tableName            = tableRows.Key;
                List <InvolvedRow> involvedRowsForTable = tableRows.Value;

                IObjectDataset dataset = _datasetResolver.GetDatasetByInvolvedRowTableName(
                    tableName, element.QualityCondition);
                Assert.NotNull(dataset, "unable to resolve dataset");

                result.Add(CreateInvolvedTable(dataset, involvedRowsForTable));
            }

            return(result);
        }
Esempio n. 4
0
        protected override int ExecuteCore(IRow row, int tableIndex)
        {
            int errorCount = 0;
            var feature    = row as IFeature;

            if (feature == null)
            {
                return(errorCount);
            }

            var geometryCollection = feature.Shape as IGeometryCollection;

            if (geometryCollection == null)
            {
                return(errorCount);
            }

            SegmentsPlaneProvider segmentsPlaneProvider = GetPlaneProvider(feature);
            SegmentsPlane         segmentsPlane;

            while ((segmentsPlane = segmentsPlaneProvider.ReadPlane()) != null)
            {
                Plane3D plane;
                try
                {
                    plane = segmentsPlane.Plane;
                }
                catch (Exception e)
                {
                    errorCount += ReportInvalidPlane(
                        $"Unable to determine plane: {e.Message}", segmentsPlane,
                        feature);
                    continue;
                }

                if (!plane.IsDefined)
                {
                    errorCount += ReportInvalidPlane(
                        "The segments of this face are collinear and do not define a valid plane",
                        segmentsPlane, feature);
                    continue;
                }

                double coplanarityTolerance = GeomUtils.AdjustCoplanarityTolerance(plane,
                                                                                   _coplanarityTolerance,
                                                                                   _zResolution,
                                                                                   _xyResolution);

                double maxOffset     = -1;
                int    segmentsCount = 0;
                foreach (SegmentProxy segment in segmentsPlane.Segments)
                {
                    segmentsCount++;

                    IPnt point = segment.GetStart(true);
                    //double f = normal.X * point.X + normal.Y * point.Y +
                    //           normalZ * point[2] + nf;

                    // double offset = Math.Abs(f);
                    double offset = plane.GetDistanceAbs(point.X, point.Y, point[2]);

                    if (offset <= coplanarityTolerance)
                    {
                        continue;
                    }

                    maxOffset = Math.Max(offset, maxOffset);
                }

                if (segmentsCount < 3)
                {
                    // TODO no need to check here once the plane is undefined in this case --> REMOVE
                    const string description =
                        "The segments of this face are collinear and do not define a valid plane";
                    IGeometry errorGeometry = GetErrorGeometry(feature.Shape.GeometryType,
                                                               segmentsPlane.Segments);
                    errorCount += ReportError(description, errorGeometry,
                                              Codes[Code.FaceDoesNotDefineValidPlane],
                                              null,
                                              row);
                    continue;
                }

                if (maxOffset > 0)
                {
                    string comparison = FormatLengthComparison(
                        maxOffset, ">", _coplanarityTolerance,
                        feature.Shape.SpatialReference);
                    string description =
                        $"Face with {segmentsCount} segments is not planar, max. offset = {comparison}";
                    IGeometry errorGeometry = GetErrorGeometry(feature.Shape.GeometryType,
                                                               segmentsPlane.Segments);
                    errorCount += ReportError(description, errorGeometry,
                                              Codes[Code.FaceNotCoplanar],
                                              TestUtils.GetShapeFieldName(feature),
                                              InvolvedRowUtils.GetInvolvedRows(row),
                                              new object[] { maxOffset });
                }
            }

            return(errorCount);
        }
Esempio n. 5
0
            private IEnumerable <InvolvedRow> GetInvolvedRows(
                [CanBeNull] out IGeometry errorGeometry,
                out bool incompleteInvolvedRows)
            {
                errorGeometry = null;
                var result = new List <InvolvedRow>();

                const int maxInvolvedRows = 25;

                incompleteInvolvedRows = false;

                foreach (DistinctValue distinctValue in GetDistinctValuesForReport())
                {
                    if (result.Count >= maxInvolvedRows)
                    {
                        incompleteInvolvedRows = true;
                        break;
                    }

                    foreach (TestRowReference[] oidTuple in distinctValue.RowOIDTuples)
                    {
                        if (result.Count >= maxInvolvedRows)
                        {
                            incompleteInvolvedRows = true;
                            break;
                        }

                        if (!IsJoinedTable)
                        {
                            // simple tables have just one oid in the tuple:
                            result.Add(CreateInvolvedRow(oidTuple[0], _tableNames));
                        }
                        else
                        {
                            Assert.NotNull(_relatedTables, "_relatedTables");

                            var relatedTableIndex = 0;
                            var relatedRows       =
                                new List <InvolvedRow>(
                                    Assert.NotNull(_relatedTables).Related.Count);

                            foreach (RelatedTable relatedTable in Assert
                                     .NotNull(_relatedTables)
                                     .Related)
                            {
                                int relatedTableOID =
                                    oidTuple[relatedTableIndex].ObjectId;
                                relatedTableIndex++;

                                if (relatedTableOID < 0)
                                {
                                    continue;
                                }

                                relatedRows.Add(
                                    new InvolvedRow(relatedTable.TableName,
                                                    relatedTableOID));

                                // why just use the first here?
                                //if (errorGeometry == null)
                                //{
                                //    errorGeometry = relatedTable.GetGeometry(relatedTableOID);
                                //}
                            }

                            InvolvedRowUtils.AddUniqueInvolvedRows(result, relatedRows);
                        }
                    }
                }

                return(result);
            }
        protected override int ExecuteCore(IRow row, int tableIndex)
        {
            if (tableIndex >= _polygonClassesCount)
            {
                return(NoError);
            }

            if (_queryFilter == null)
            {
                InitFilter();
                Assert.NotNull(_queryFilter, "_queryFilter");
            }

            var       feature         = (IFeature)row;
            IGeometry containingShape = feature.Shape;

            if (containingShape == null || containingShape.IsEmpty)
            {
                return(NoError);
            }

            IPolyline line = containingShape as IPolyline;

            if (line != null && PolylineUsage != PolylineUsage.AsIs)
            {
                if (!line.IsClosed)
                {
                    if (PolylineUsage == PolylineUsage.AsPolygonIfClosedElseReportIssue)
                    {
                        return(ReportError("Unclosed line", line, Codes[Code.NotClosed_Line], null,
                                           InvolvedRowUtils.GetInvolvedRows(feature)));
                    }

                    if (PolylineUsage == PolylineUsage.AsPolygonIfClosedElseIgnore)
                    {
                        return(NoError);
                    }
                }
                else
                {
                    containingShape = GeometryFactory.CreatePolygon(line);
                }
            }

            if (IsPolygonFullyChecked(row.OID, tableIndex))
            {
                return(NoError);
            }

            PolygonPoints polygonPoints = GetPolygonPoints(feature, tableIndex);

            if (_relevantPointCondition == null)
            {
                _relevantPointCondition = new RelevantPointCondition(
                    _relevantPointConditionSql, GetSqlCaseSensitivity());
            }

            for (int pointClassIndex = _polygonClassesCount;
                 pointClassIndex < _totalClassesCount;
                 pointClassIndex++)
            {
                _queryFilter[pointClassIndex].Geometry = containingShape;

                foreach (IRow pointRow in Search(InvolvedTables[pointClassIndex],
                                                 _queryFilter[pointClassIndex],
                                                 _helper[pointClassIndex]))
                {
                    var pointFeature = (IFeature)pointRow;
                    // point feature is POINT, polygon feature is POLYGON
                    if (!_relevantPointCondition.IsFulfilled(
                            pointFeature, pointClassIndex,
                            row, tableIndex))
                    {
                        continue;
                    }

                    polygonPoints.AddPointFeature(pointFeature, pointClassIndex);
                }
            }

            return(NoError);
        }
Esempio n. 7
0
        private int CheckDistance([NotNull] IPoint p0, [NotNull] IPoint p1,
                                  [NotNull] IRow row0, int tableIndex0,
                                  [NotNull] IRow row1, int tableIndex1,
                                  bool coincidentIsError,
                                  out bool validRelationConstraintFulfilled)
        {
            double pointDistanceSquared = GeometryMathUtils.GetDistanceSquared(p0, p1, _is3D);

            validRelationConstraintFulfilled = false;

            bool isCoincident = pointDistanceSquared <= _toleranceSquared;

            if ((coincidentIsError || !isCoincident) &&
                pointDistanceSquared < _searchDistanceSquared)
            {
                if (_validRelationConstraint.IsFulfilled(row0, tableIndex0,
                                                         row1, tableIndex1))
                {
                    validRelationConstraintFulfilled = true;
                    return(NoError);
                }

                IGeometry errorGeometry = CreateErrorGeometry(p0, p1);

                double dist        = Math.Sqrt(pointDistanceSquared);
                string description = string.Format("Nodedistance {0}",
                                                   FormatLengthComparison(dist, "<",
                                                                          SearchDistance,
                                                                          p0.SpatialReference));

                IssueCode issueCode = _validRelationConstraintSql == null
                                                              ? Codes[Code.NodeDistanceTooSmall]
                                                              : Codes[Code.NodeDistanceTooSmall_ConstraintNotFulfilled];

                // TODO differentiate issue code if exactly coincident?
                return(ReportError(description, errorGeometry,
                                   issueCode, TestUtils.GetShapeFieldName(row0),
                                   InvolvedRowUtils.GetInvolvedRows(row0, row1),
                                   new object[] { dist }));
            }

            if (_maxZDifference >= 0 && pointDistanceSquared < _searchDistanceSquared)
            {
                double z0 = p0.Z;
                double z1 = p1.Z;

                double absZDifference = Math.Abs(z0 - z1);

                if (absZDifference > _maxZDifference)
                {
                    if (MathUtils.AreSignificantDigitsEqual(absZDifference, _maxZDifference))
                    {
                        // difference is not significant
                        return(NoError);
                    }

                    if (_validRelationConstraint.IsFulfilled(row0, tableIndex0,
                                                             row1, tableIndex1))
                    {
                        validRelationConstraintFulfilled = true;
                        return(NoError);
                    }

                    IGeometry errorGeometry = CreateErrorGeometry(p0, p1);

                    string description = string.Format("Z-Difference {0}",
                                                       FormatComparison(absZDifference, ">",
                                                                        _maxZDifference, "N1"));
                    IssueCode issueCode = _validRelationConstraintSql == null
                                                                      ? Codes[Code.ZDifferenceTooLarge]
                                                                      : Codes[
                        Code.ZDifferenceTooLarge_ConstraintNotFulfilled];

                    return(ReportError(description, errorGeometry,
                                       issueCode, TestUtils.GetShapeFieldName(row0),
                                       InvolvedRowUtils.GetInvolvedRows(row0, row1),
                                       new object[] { absZDifference }));
                }
            }

            return(NoError);
        }