/// <summary> /// Find elements either contained, containing or intersecting polygon. /// <para> /// If no elements are found, an empty list is returned. /// </para> /// </summary> public IList <int> FindElements(Polygon polygon) { if (_elementSearchTree == null) { SetupElementSearch(); } Envelope targetEnvelope = polygon.EnvelopeInternal; IList <int> potentialElmts = _elementSearchTree.Query(targetEnvelope); List <int> result = new List <int>(); // Loop over all potential elements for (int i = 0; i < potentialElmts.Count; i++) { int element = potentialElmts[i]; // Fast-lane check: When there is no overlap even by the envelopes if (!targetEnvelope.Intersects(_mesh.ElementEnvelopeInternal(element))) { continue; } // More detailed check for actual overlap Polygon elementPolygon = _mesh.ElementToPolygon(element); if (elementPolygon.Intersects(polygon)) { result.Add(element); } } return(result); }
/// <summary> /// Find elements either contained, containing or intersecting the polygon. /// <para> /// This method can be used if only some elements of the mesh is to be included /// in the weight calculations. /// </para> /// <para> /// If polygon is totally contained within one mesh element, then 1 element is returned. /// If polygon partially falls outside of the grid, only elements within grid are returned. /// </para> /// <param name="polygon">Polygon or multi-polygon</param> /// <param name="elements">List of elements</param> /// </summary> public List <ElementWeight> CalculateWeights(Geometry polygon, IList <int> elements) { if (!(polygon is MultiPolygon) && !(polygon is Polygon)) { throw new Exception("Cannot calculate weights for geometry of type: " + polygon.GeometryType); } Envelope targetEnvelope = polygon.EnvelopeInternal; //// It should be faster to use than the polygon directly? //PreparedPolygon prepolygon = new PreparedPolygon(polygon); List <ElementWeight> result = new List <ElementWeight>(); // Total intersecting area double totalArea = 0; // Loop over all potential elements int elementsCount = elements?.Count ?? _mesh.NumberOfElements; for (int i = 0; i < elementsCount; i++) { int element = elements != null ? elements[i] : i; // Fast-lane check: When there is no overlap even by the envelopes if (!targetEnvelope.Intersects(_mesh.ElementEnvelopeInternal(element))) { continue; } Polygon elementPolygon = _mesh.ElementToPolygon(element); Geometry intersection = elementPolygon.Intersection(polygon); if (!intersection.IsEmpty) { // Target polygon and element polygon has an overlap. // If target polygon fully contains the element polygon, this is the element area // If element polygon fully contains the target polygon, this is the polygon area double intersectingArea = intersection.Area; totalArea += intersectingArea; if (WeightType == WeightType.Fraction) { result.Add(new ElementWeight(element, intersectingArea / elementPolygon.Area)); } else { result.Add(new ElementWeight(element, intersectingArea)); } } } IntersectionArea = totalArea; if (result.Count == 0 || totalArea == 0) { return(null); } // When Weight-based calculations, weight with the total intersecting area if (WeightType == WeightType.Weight) { for (int i = 0; i < result.Count; i++) { ElementWeight elmtWeight = result[i]; elmtWeight.Weight /= totalArea; result[i] = elmtWeight; } } return(result); }