private int CheckPathEndPoints([NotNull] IFeature feature, [NotNull] IPath path) { var vertices = (IPointCollection)path; // TODO should use segment-based angle calculation (only for non-linear segments) int pointCount = vertices.PointCount; vertices.QueryPoint(0, _firstSegmentStartPoint); vertices.QueryPoint(1, _firstSegmentEndPoint); double firstSegmentSquaredLength = GeometryMathUtils.GetDistanceSquared(_firstSegmentEndPoint, _firstSegmentStartPoint, _is3D); vertices.QueryPoint(pointCount - 2, _lastSegmentStartPoint); vertices.QueryPoint(pointCount - 1, _lastSegmentEndPoint); double lastSegmentSquaredLength = GeometryMathUtils.GetDistanceSquared(_lastSegmentStartPoint, _lastSegmentEndPoint, _is3D); int errorCount = 0; int compareTableIndex = -1; bool skip = IgnoreUndirected; foreach (var table in InvolvedTables) { var compareFeatureClass = (IFeatureClass)table; compareTableIndex++; _helper[compareTableIndex].MinimumOID = -1; if (feature.Table == compareFeatureClass) { skip = false; if (IgnoreUndirected) { _helper[compareTableIndex].MinimumOID = feature.OID; } } if (skip) { continue; } errorCount += ExecutePoint(_firstSegmentStartPoint, _firstSegmentEndPoint, firstSegmentSquaredLength, compareFeatureClass, compareTableIndex, feature); errorCount += ExecutePoint(_lastSegmentEndPoint, _lastSegmentStartPoint, lastSegmentSquaredLength, compareFeatureClass, compareTableIndex, feature); } return(errorCount); }
private int CheckSegments([NotNull] ISegmentCollection segments, [NotNull] IRow row) { IEnumSegment enumSegments = segments.EnumSegments; enumSegments.Reset(); ISegment segment; int partIndex = -1; int segmentIndex = -1; enumSegments.Next(out segment, ref partIndex, ref segmentIndex); bool recycling = enumSegments.IsRecycling; int errorCount = 0; while (segment != null) { double slopeRadians = GeometryMathUtils.CalculateSlope(segment); if (slopeRadians > _limit) { string description = string.Format( "Slope angle {0} > {1}", FormatAngle(slopeRadians, "N2"), FormatAngle(_limit, "N2")); IPolyline errorGeometry = GeometryFactory.CreatePolyline(segment); errorCount += ReportError(description, errorGeometry, Codes[Code.SlopeTooSteep], TestUtils.GetShapeFieldName(row), new object[] { MathUtils.ToDegrees(slopeRadians) }, row); } if (recycling) { // release the segment, otherwise "pure virtual function call" occurs // when there are certain circular arcs (IsLine == true ?) Marshal.ReleaseComObject(segment); } enumSegments.Next(out segment, ref partIndex, ref segmentIndex); } return(errorCount); }
/// <summary> /// looks if the three input segments are smooth /// </summary> /// <param name="threeSegments">Input segments. Only the first three segments will be used.</param> /// <param name="row"></param> /// <returns>Are segments smooth?</returns> private int CheckThreeSegments([NotNull] IList <ISegment> threeSegments, [NotNull] IRow row) { double anglechange = GeometryMathUtils.CalculateSmoothness(threeSegments[0], threeSegments[1], threeSegments[2]); if (Math.Abs(anglechange) <= _limit) { return(NoError); } string description = string.Format("Smoothness parameter {0:N4} > {1:N4}", Math.Abs(anglechange), _limit); IGeometry errorGeometry = GetErrorGeometry(threeSegments[1]); return(ReportError(description, errorGeometry, Codes[Code.AbruptChangeInSlopeAngle], TestUtils.GetShapeFieldName(row), row)); }
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); }