private bool CutFeature([NotNull] IFeature feature, [NotNull] IPolyline cutPolyline, ChangeAlongZSource?zSource = null) { IGeometry selectedGeometry = feature.Shape; if (GeometryUtils.Disjoint(cutPolyline, selectedGeometry)) { return(false); } if (FeatureToCutPredicate != null && !FeatureToCutPredicate(selectedGeometry, cutPolyline)) { return(false); } _msg.DebugFormat("Cutting feature {0}", GdbObjectUtils.ToString(feature)); IGeometry geometryToCut = GeometryFactory.Clone(selectedGeometry); CutPolyline usedCutLine = null; if (ProcessedCutLines != null) { usedCutLine = new CutPolyline(feature.OID); ProcessedCutLines.Add(usedCutLine); } IList <IGeometry> resultGeometries; switch (geometryToCut.GeometryType) { case esriGeometryType.esriGeometryPolygon: resultGeometries = CutGeometryUtils.TryCut( (IPolygon)geometryToCut, cutPolyline, zSource ?? DetermineZSource(feature)); break; case esriGeometryType.esriGeometryPolyline: resultGeometries = _networkFeatureCutter?.IsNetworkEdge(feature) == true ? GetNetworkSplitPoints(cutPolyline, geometryToCut) : CutGeometryUtils.TryCut((IPolyline)geometryToCut, cutPolyline); break; case esriGeometryType.esriGeometryMultiPatch: resultGeometries = CutGeometryUtils.TryCut((IMultiPatch)geometryToCut, cutPolyline, zSource ?? DetermineZSource(feature), usedCutLine, DegenerateMultipatchFootprintAction) .Values.Cast <IGeometry>() .ToList(); break; default: throw new InvalidOperationException( $"Unsupported geometry type: {geometryToCut.GeometryType}"); } if (resultGeometries != null && resultGeometries.Count > 0) { IList <IGeometry> previousResults; if (ResultGeometriesByFeature.TryGetValue(feature, out previousResults)) { foreach (IGeometry resultGeometry in resultGeometries) { previousResults.Add(resultGeometry); } } else { ResultGeometriesByFeature.Add(feature, resultGeometries); } } return(resultGeometries != null && resultGeometries.Count > 0); }
private void CutFeature3D(IFeature feature, IMultiPatch cutSurfaces) { IGeometry selectedGeometry = feature.Shape; if (GeometryUtils.Disjoint(cutSurfaces, selectedGeometry)) { return; } if (GeometryUtils.AreEqual(cutSurfaces, selectedGeometry)) { return; } if (FeatureToCutPredicate != null && !FeatureToCutPredicate(selectedGeometry, cutSurfaces)) { return; } // TODO: Multipatches should be cut if its footprint can be cut. However, if multiple ring groups exist, // that are not connected (touch along a line) in 3D, the rings should be grouped into connected parts. List <CutPolyline> cutPolylines = IntersectionUtils.GetIntersectionLines3D((IMultiPatch)selectedGeometry, cutSurfaces).ToList(); foreach (CutPolyline cutPoline in cutPolylines) { cutPoline.ObjectId = feature.OID; // Add the calculated lines for reference and traceability, filtering and subsequent cutting // with Success field equals null ProcessedCutLines?.Add(cutPoline); } if (cutPolylines.Count > 0) { var success = false; // TODO: Consider filter option for cut lines or even a clever path selection logic to avoid junctions: // Only use cut lines that are in the plane to connect disjoint cut line paths that are positive or negative // Consider adding an option to delete the negative or the positive side of the rings. var cutLineToUse = (IPolyline)GeometryUtils.Union( cutPolylines.Select(c => c.Polyline).ToList()); GeometryUtils.Simplify(cutLineToUse, true, false); if (!cutLineToUse.IsEmpty) { try { success = CutFeature(feature, cutLineToUse, ChangeAlongZSource.SourcePlane); } catch (Exception e) { _msg.WarnFormat("Cutting multipatch feature {0} failed.", GdbObjectUtils.ToString(feature)); _msg.Debug(e); } var appliedCutline = new CutPolyline(cutLineToUse); appliedCutline.SuccessfulCut = success; ProcessedCutLines?.Add(appliedCutline); } } }