/// <summary> /// Collect edges from area inputs which should be in the result but /// which have not been included in a result area. /// </summary> /// <remarks> /// This happens ONLY: /// <list type="bullet"> /// <item> /// <description> /// During an intersection when the boundaries of two areas touch /// in a line segment. /// </description> /// </item> /// <item> /// <description>OR as a result of a dimensional collapse.</description> /// </item> /// </list> /// </remarks> private void CollectBoundaryTouchEdge(DirectedEdge de, OverlayType opCode, ArrayList edges) { Label label = de.Label; if (de.LineEdge) { return; // only interested in area edges } if (de.Visited) { return; // already processed } if (de.InteriorAreaEdge) { return; // added to handle dimensional collapses } if (de.Edge.InResult) { return; // if the edge linework is already included, don't include it again } // sanity check for labelling of result edgerings Debug.Assert(!(de.InResult || de.Sym.InResult) || !de.Edge.InResult); // include the linework if it's in the result of the operation if (OverlayOp.IsResultOfOp(label, opCode) && opCode == OverlayType.Intersection) { edges.Add(de.Edge); de.VisitedEdge = true; } }
/// <summary> /// /// </summary> /// <param name="opCode"></param> /// <returns></returns> public IGeometry GetResultGeometry(SpatialFunction opCode) { IGeometry[] prepGeom = Snap(); IGeometry result = OverlayOp.Overlay(prepGeom[0], prepGeom[1], opCode); return(PrepareResult(result)); }
/// <summary> /// Determines nodes which are in the result, and creates /// {@link Point}s for them. /// /// This method determines nodes which are candidates for the result via their /// labelling and their graph topology. /// /// </summary> /// <param name="opCode">the overlay operation /// </param> private void ExtractNonCoveredResultNodes(OverlayType opCode) { // Add nodes from edge intersections which have not already been included in the result for (IEnumerator nodeit = op.Graph.Nodes.GetEnumerator(); nodeit.MoveNext();) { Node n = (Node)nodeit.Current; // filter out nodes which are known to be in the result if (n.InResult) { continue; } // if an incident edge is in the result, then the node coordinate is included already if (n.IsIncidentEdgeInResult) { continue; } if (n.Edges.Degree == 0 || opCode == OverlayType.Intersection) { // For nodes on edges, only INTERSECTION can result in // edge nodes being included even // if none of their incident edges are included Label label = n.Label; if (OverlayOp.IsResultOfOp(label, opCode)) { FilterCoveredNodeToPoint(n); } } } }
/// <summary> /// Computes a <c>Geometry</c> representing the point-set which is /// common to both <c>a</c> and <c>b</c> Geometry. /// </summary> /// <param name="a">The 1st <c>Geometry</c></param> /// <param name="b">The 2nd <c>Geometry</c></param> /// <returns>A geometry representing the point-set common to the two <c>Geometry</c>s.</returns> /// <seealso cref="Geometry.Intersection"/> public virtual Geometry Intersection(Geometry a, Geometry b) { /** * TODO: MD - add optimization for P-A case using Point-In-Polygon */ // special case: if one input is empty ==> empty if (a.IsEmpty || b.IsEmpty) { return(OverlayOp.CreateEmptyResult(SpatialFunction.Intersection, a, b, a.Factory)); } // compute for GCs // (An inefficient algorithm, but will work) // TODO: improve efficiency of computation for GCs if (a.OgcGeometryType == OgcGeometryType.GeometryCollection) { var g2 = b; return(GeometryCollectionMapper.Map( (GeometryCollection)a, g => g.Intersection(g2))); } // No longer needed since GCs are handled by previous code //CheckNotGeometryCollection(a, b); return(Overlay(a, b, SpatialFunction.Intersection)); }
/// <summary> /// Computes a <c>Geometry</c> representing the point-set /// which is contained in both input <c>Geometry</c>s . /// </summary> /// <param name="a">The 1st <c>Geometry</c></param> /// <param name="b">The 2nd <c>Geometry</c></param> /// <returns>A point-set combining the points of /// <c>Geometry</c>'s <c>a</c> and <c>b</c>. /// </returns> /// <seealso cref="Geometry.Union(Geometry)"/> public virtual Geometry Union(Geometry a, Geometry b) { // handle empty geometry cases if (a.IsEmpty || (b == null || b.IsEmpty)) { // both empty - check dimensions if (a.IsEmpty && (b == null || b.IsEmpty)) { return(OverlayOp.CreateEmptyResult(SpatialFunction.Union, a, b, a.Factory)); } // special case: if either input is empty ==> result = other arg if (a.IsEmpty) { return(b.Copy()); } if (b == null || b.IsEmpty) { return(a.Copy()); } } // TODO: optimize if envelopes of geometries do not intersect CheckNotGeometryCollection(a, b); return(Overlay(a, b, SpatialFunction.Union)); }
/// <summary> /// Computes a <c>Geometry</c> representing the closure of the point-set /// which is the union of the points in <c>Geometry</c> <c>a</c> which are not /// contained in the Geometry <c>b</c>, /// with the points in the <c>b</c> Geometry not contained in the <c>Geometry</c> <c>a</c>. /// </summary> /// <param name="a">The 1st <c>Geometry</c></param> /// <param name="b">The 2nd <c>Geometry</c></param> /// <returns> /// A Geometry representing the point-set symmetric difference /// of <c>Geometry</c>'s <c>a</c> and <c>b</c>. /// </returns> /// <seealso cref="Geometry.SymmetricDifference(Geometry)"/> public virtual Geometry SymmetricDifference(Geometry a, Geometry b) { // handle empty geometry cases if (a.IsEmpty || (b == null || b.IsEmpty)) { // both empty - check dimensions if (a.IsEmpty && (b == null || b.IsEmpty)) { return(OverlayOp.CreateEmptyResult(SpatialFunction.SymDifference, a, b, a.Factory)); } // special case: if either input is empty ==> result = other arg if (a.IsEmpty) { return(b.Copy()); } if (b == null || b.IsEmpty) { return(a.Copy()); } } CheckNotGeometryCollection(a, b); return(Overlay(a, b, SpatialFunction.SymDifference)); }
public IGeometry GetResultGeometry(SpatialFunction opCode) { IGeometry result = null; var isSuccess = false; try { result = OverlayOp.Overlay(geom[0], geom[1], opCode); var isValid = true; // not needed if noding validation is used // boolean isValid = OverlayResultValidator.isValid(geom[0], geom[1], OverlayOp.INTERSECTION, result); // if (isValid) isSuccess = true; } catch (Exception ex) { // Ignore this exception, since the operation will be rerun Debug.WriteLine(ex); } if (!isSuccess) { // This may still throw an exception - just let it go if it does result = SnapOverlayOp.Overlay(geom[0], geom[1], opCode); } return(result); }
/// <summary> /// /// </summary> /// <param name="opCode"></param> /// <returns></returns> public Geometry GetResultGeometry(SpatialFunction opCode) { var prepGeom = Snap(_geom); var result = OverlayOp.Overlay(prepGeom[0], prepGeom[1], opCode); return(PrepareResult(result)); }
///<summary> /// Returns a set combining the points in this Geometry not in other, and the points in other not /// in this Geometry. ///</summary> ///<remarks>This method returns the closure of the resultant Geometry.</remarks> ///<param name="geometry"> the Geometry with which to compute the symmetric difference.</param> ///<returns>Returns the point set symmetric difference of this Geometry with other geometry.</returns> public virtual Geometry SymDifference(Geometry geometry) { CheckNotGeometryCollection(this); CheckNotGeometryCollection(geometry); CheckEqualSRID(geometry); CheckEqualPrecisionModel(geometry); return OverlayOp.Overlay(this, geometry, OverlayOp.SymDifference); }
///<summary> /// Returns a Geometry representing all the points in this Geometry and other. ///</summary> ///<param name="geometry"> the Geometry with which to compute the union </param> ///<returns>Returns a set combining the points of this Geometry and the points of other geometry.</returns> public virtual Geometry Union(Geometry geometry) { CheckNotGeometryCollection(this); CheckNotGeometryCollection(geometry); CheckEqualSRID(geometry); CheckEqualPrecisionModel(geometry); return OverlayOp.Overlay(this, geometry, OverlayOp.Union); }
public LineBuilder(OverlayOp op, GeometryFactory geometryFactory, PointLocator ptLocator) { lineEdgesList = new ArrayList(); resultLineList = new GeometryList(); this.op = op; this.geometryFactory = geometryFactory; this.ptLocator = ptLocator; }
private Exception TryOverlay(Geometry g1, Geometry g2) { Exception ex = null; try { OverlayOp.Overlay(g1, g2, SpatialFunction.Intersection); } catch (Exception e) { ex = e; } return(ex); }
private static bool IsValidResult(SpatialFunction overlayOp, Location[] location) { bool expectedInterior = OverlayOp.IsResultOfOp(location[0], location[1], overlayOp); bool resultInInterior = (location[2] == Location.Interior); // MD use simpler: boolean isValid = (expectedInterior == resultInInterior); bool isValid = !(expectedInterior ^ resultInInterior); if (!isValid) { ReportResult(overlayOp, location, expectedInterior); } return(isValid); }
/// <summary> /// Collect line edges which are in the result. /// Line edges are in the result if they are not part of /// an area boundary, if they are in the result of the overlay operation, /// and if they are not covered by a result area. /// </summary> /// <param name="de">the directed edge to test</param> /// <param name="opCode">the overlap operation</param> /// <param name="edges">the list of included line edges</param> private void CollectLineEdge(DirectedEdge de, OverlayType opCode, ArrayList edges) { Label label = de.Label; Edge e = de.Edge; // include L edges which are in the result if (de.LineEdge) { if (!de.Visited && OverlayOp.IsResultOfOp(label, opCode) && !e.Covered) { edges.Add(e); de.VisitedEdge = true; } } }
/// <summary> /// Cuts the given linestring in one of more segments. /// </summary> /// <param name="tilePolygon">The tile polygon.</param> /// <param name="lineString">The linestring.</param> /// <returns>One or more segments.</returns> public static IEnumerable <LineString> Cut(this Polygon tilePolygon, LineString lineString) { var op = new OverlayOp(lineString, tilePolygon); var intersection = op.GetResultGeometry(SpatialFunction.Intersection); if (intersection.IsEmpty) { yield break; } switch (intersection) { case LineString ls: // intersection is a linestring. yield return(ls); yield break; case GeometryCollection gc: { foreach (var geometry in gc.Geometries) { switch (geometry) { case LineString ls0: yield return(ls0); break; case Point _: // The linestring only has a single point in this tile // We skip it // TODO check if this is correct continue; default: throw new Exception( $"{nameof(LineStringTiler)}.{nameof(Cut)} failed: A geometry was found in the intersection that wasn't a {nameof(LineString)}."); } } yield break; } default: throw new Exception($"{nameof(LineStringTiler)}.{nameof(Cut)} failed: Unknown result."); } }
/// <summary> /// Computes a <c>Geometry</c> representing the closure of the point-set /// of the points contained in this <c>Geometry</c> that are not contained in /// the <c>other</c> Geometry. /// </summary> /// <param name="a">The 1st <c>Geometry</c></param> /// <param name="b">The 2nd <c>Geometry</c></param> /// <returns> /// A Geometry representing the point-set difference /// of <c>Geometry</c>'s <c>a</c> and <c>b</c>. /// </returns> /// <seealso cref="Geometry.Difference(Geometry)"/> public virtual Geometry Difference(Geometry a, Geometry b) { // special case: if A.isEmpty ==> empty; if B.isEmpty ==> A if (a.IsEmpty) { return(OverlayOp.CreateEmptyResult(SpatialFunction.Difference, a, b, a.Factory)); } if (b == null || b.IsEmpty) { return(a.Copy()); } CheckNotGeometryCollection(a, b); return(Overlay(a, b, SpatialFunction.Difference)); }
public IGeometry GetResultGeometry(SpatialFunction opCode) { IGeometry result = null; var isSuccess = false; Exception savedException = null; try { // try basic operation with input geometries result = OverlayOp.Overlay(_geom[0], _geom[1], opCode); var isValid = true; // not needed if noding validation is used // boolean isValid = OverlayResultValidator.isValid(geom[0], geom[1], OverlayOp.INTERSECTION, result); // if (isValid) isSuccess = true; } catch (Exception ex) { savedException = ex; //// Ignore this exception, since the operation will be rerun //Debug.WriteLine(ex); //Console.WriteLine(ex.Message)); //Console.WriteLine("Geom 0: " + geom[0]); //Console.WriteLine("Geom 1: " + geom[1]); } if (!isSuccess) { // this may still throw an exception // if so, throw the original exception since it has the input coordinates try { result = SnapOverlayOp.Overlay(_geom[0], _geom[1], opCode); } catch (Exception) { throw savedException; } } return(result); }
public Geometry GetResultGeometry(SpatialFunction opCode) { Geometry result = null; bool isSuccess = false; ExceptionDispatchInfo savedException = null; try { // try basic operation with input geometries result = OverlayOp.Overlay(_geom[0], _geom[1], opCode); bool isValid = true; // not needed if noding validation is used // boolean isValid = OverlayResultValidator.isValid(geom[0], geom[1], OverlayOp.INTERSECTION, result); // if (isValid) isSuccess = true; } catch (Exception ex) { savedException = ExceptionDispatchInfo.Capture(ex); // Ignore this exception, since the operation will be rerun } if (!isSuccess) { // this may still throw an exception // if so, throw the original exception since it has the input coordinates try { result = SnapOverlayOp.Overlay(_geom[0], _geom[1], opCode); } catch (Exception) { savedException.Throw(); } } return(result); }
public PointBuilder(OverlayOp op, GeometryFactory geometryFactory) { this.op = op; this.geometryFactory = geometryFactory; this.resultPointList = new GeometryList(); }
/// <summary> /// Computes a unary union with no extra optimization, and no short-circuiting. /// </summary> /// <remarks> /// Due to the way the overlay operations are implemented, this is still efficient in the case of linear and puntal geometries. /// </remarks> /// <param name="g0">A geometry</param> /// <returns>The union of the input geometry</returns> private IGeometry UnionNoOpt(IGeometry g0) { var empty = _geomFact.CreatePoint(); return(OverlayOp.Overlay(g0, empty, SpatialFunction.Union)); }
static void Main(string[] args) { BasicConfigurator.Configure(); string geoJSONdatafile = @"D:\research\wifidata\network_minspan_001.geojson"; var networksInRange = new HashSet <string>(new string[] { "bc:ae:c5:c3:71:66", "00:20:a6:5d:5f:7c", "00:22:3f:7a:76:39" }); var json = File.ReadAllText(geoJSONdatafile); var coll = (JObject)JsonConvert.DeserializeObject(json); List <JObject> found = new List <JObject>(); List <Polygon> polygons = new List <Polygon>(); foreach (JObject feature in coll["features"]) { JObject atts = (JObject)feature["properties"]; var bssid = (string)atts["bssid"]; if (networksInRange.Contains(bssid)) { found.Add(feature); //polygons.Add(ReadPolygon((JObject)feature["geometry"])); } } //argh. GeoJsonReader reader = new GeoJsonReader(); //var result = reader.Read<Polygon>(json); for (int i = 0; i < found.Count; i++) { var feat = found[i]; JObject geom = (JObject)feat["geometry"]; Polygon p = ReadPolygon(geom); polygons.Add(p); if (p != null) { _log.InfoFormat("found {0} : {1} ", feat["bssid"], p.ToText()); } } IGeometry result = null; if (polygons.Count > 1) { for (int i = 0; i < polygons.Count - 1; i++) { if ((result == null) || (result.IsEmpty)) { result = polygons[i]; } result = OverlayOp.Overlay(result, polygons[i + 1], SpatialFunction.Intersection); } } _log.InfoFormat("YOU ARE HERE {0} ", result); Clipboard.SetText(result.ToString()); _log.Info("Done -- Copied to clipboard"); }
///<summary> /// Computes a unary union with no extra optimization, and no short-circuiting. ///</summary> /// <remarks> /// Due to the way the overlay operations are implemented, this is still efficient in the case of linear and puntal geometries. /// </remarks> /// <param name="g0">A geometry</param> /// <returns>The union of the input geometry</returns> private IGeometry UnionNoOpt(IGeometry g0) { IGeometry empty = _geomFact.CreatePoint((Coordinate)null); return(OverlayOp.Overlay(g0, empty, SpatialFunction.Union)); }
public static FeatureClassSDO Intersect(this FeatureClassSDO featureClassSelf, FeatureClassSDO featureClassOther) { FeatureClassSDO newFeatureClass = null; try { if (featureClassSelf == null || featureClassOther == null) { throw new ArgumentException("对象未实例化"); } if (featureClassSelf.GeometryTypeNet != featureClassOther.GeometryTypeNet) { throw new ArgumentException("空间对象类型错误"); } if (CompareProperties(featureClassSelf.spatialReference, featureClassOther.spatialReference, typeof(object))) { throw new ArgumentException("空间坐标系不一致"); } newFeatureClass = new FeatureClassSDO() { Name = $"{featureClassSelf.Name}_{featureClassOther.Name}", DisplayFieldName = $"{featureClassSelf.DisplayFieldName}_{featureClassOther.DisplayFieldName}", Fields = featureClassSelf.Fields, GeometryType = featureClassSelf.GeometryType, GeometryTypeNet = featureClassSelf.GeometryTypeNet, spatialReference = featureClassSelf.spatialReference }; foreach (var item in featureClassOther.Fields) { if (item.Type == enumFieldType.esriFieldTypeGeometry || item.Name.ToLower() == "shape_area") { continue; } newFeatureClass.Fields.Add(new Field() { Alias = $"{featureClassOther.Name}_{item.Alias}", Type = item.Type, Name = $"{featureClassOther.Name}_{item.Name}" }); } int groupCount = featureClassOther.Features.Count / SpatialDataObtain.MinWorkThreadCount; Parallel.ForEach(featureClassOther.Features, (otherItem) => { foreach (var selfItem in featureClassSelf.Features) { if (otherItem.Geometry.Intersects(selfItem.Geometry)) { OverlayOp overlayOp = new OverlayOp(otherItem.Geometry, selfItem.Geometry); Geometry newGeometry = overlayOp.GetResultGeometry(SpatialFunction.Intersection); Feature newFeature = new Feature(); newFeature.Attributes = new Dictionary <string, object>(selfItem.Attributes); foreach (var oterAttribute in otherItem.Attributes) { Field field = featureClassOther.Fields.Single(item => item.Name == oterAttribute.Key); if (field.Type == enumFieldType.esriFieldTypeGeometry || field.Name.ToLower() == "shape_area") { continue; } string newKey = $"{featureClassOther.Name}_{field.Name}"; newFeature.Attributes.Add(newKey, oterAttribute.Value); } newFeature.Geometry = newGeometry; newFeatureClass.AddFeature(newFeature); } } }); return(newFeatureClass); } catch (Exception e) { LogUtil.Error(e.ToString()); throw; } }