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()); }
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); }
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); }
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); }
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); }
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); }