private List <PlaneHelper> GetPlaneHelpers([NotNull] IFeature feature)
        {
            const bool            includeAssociatedParts = true;
            SegmentsPlaneProvider planeProvider          =
                SegmentsPlaneProvider.Create(feature, includeAssociatedParts);

            var indexedMultiPatch = (IIndexedMultiPatch)planeProvider.IndexedSegments;

            var result = new List <PlaneHelper>();

            SegmentsPlane segmentsPlane;

            while ((segmentsPlane = planeProvider.ReadPlane()) != null)
            {
                result.Add(PlaneHelper.Create(segmentsPlane, indexedMultiPatch, this));
            }

            return(result);
        }
        private static IEnumerable <Either <NonPlanarError, SegmentsPlane> > GetPlanarRings(
            [NotNull] IFeature planarFeature, double coplanarityTolerance)
        {
            SegmentsPlaneProvider provider =
                SegmentsPlaneProvider.Create(planarFeature, false);

            SegmentsPlane segPlane;

            while ((segPlane = provider.ReadPlane()) != null)
            {
                // check for co-planarity
                double maximumOffset;
                yield return(IsCoplanar(segPlane, planarFeature, coplanarityTolerance,
                                        out maximumOffset)
                                                     ? new Either <NonPlanarError, SegmentsPlane>(segPlane)
                                                     : new NonPlanarError("Coplanarity tolerance is exceeded",
                                                                          maximumOffset, segPlane));
            }
        }
Beispiel #3
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);
        }