/// <summary> /// Returns the list of polygons that are the sub-shapes of the minuends and that are not part of the subtrahends. /// Notice also that any overlap between the polygons in A or the polygons in B are ignored. Finally, all inputs must be positive. /// /// </summary> /// <param name="minuends">The polygons a.</param> /// <param name="subtrahends">The polygons b.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> Subtract(this IEnumerable <Polygon> minuends, IEnumerable <Polygon> subtrahends, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (CLIPPER) { return(BooleanViaClipper(ClipperLib.PolyFillType.pftPositive, ClipperLib.ClipType.ctDifference, minuends, subtrahends)); } var minuendsList = minuends.ToList(); var subtrahendsList = subtrahends as List <Polygon> ?? subtrahends.ToList(); if (double.IsNaN(tolerance)) { tolerance = GetTolerancesFromPolygons(minuendsList, subtrahendsList); } foreach (var polyB in subtrahendsList) { for (int i = minuendsList.Count - 1; i >= 0; i--) { var newPolygons = minuendsList[i].Subtract(polyB, outputAsCollectionType, tolerance); minuendsList.RemoveAt(i); foreach (var newPoly in newPolygons) { minuendsList.Insert(i, newPoly); } } } return(minuendsList); }
protected override async void OnAppearing() { base.OnAppearing(); try { var position = await Utilities.GetCurrentGeolocationAsync(); MyPosition = new Position(position.Latitude, position.Longitude); PinCollection.Add(new CustomPin() { Id = "Ryan", Position = MyPosition, Label = "Ryan", Type = PinType.Generic, Url = "http://www.ryanrauch.com/" }); PolygonCollection.Add(new Position(30.39983, -97.723719)); PolygonCollection.Add(new Position(30.40182, -97.722989)); PolygonCollection.Add(new Position(30.402172, -97.724245)); PolygonCollection.Add(new Position(30.403236, -97.72374)); PolygonCollection.Add(new Position(30.402606, -97.721659)); PolygonCollection.Add(new Position(30.399562, -97.723011)); //UpdateMapGrid(); //UpdateLocation(); //UpdatePolygons(); //MapContent.PropertyChanged += MapContent_PropertyChanged; //this has not worked yet, but used to change grids when zoomed by user //UpdateRestService(); } catch (Exception ex) { await DisplayAlert(ex.Message, ex.StackTrace, "OK"); } }
/*public async void UpdateRestService() * { * try * { * RestService svc = new RestService(); * var regions = await svc.GetRegionsAsync(); * await DisplayAlert(regions.Count.ToString(), "regions count", "OK"); * } * catch (Exception ex) * { * await DisplayAlert(ex.Message, ex.StackTrace, "OK"); * } * }*/ public void UpdatePolygons() { //ObservableCollection<Position> rockrose = new ObservableCollection<Position>(); PolygonCollection.Add(new Position(30.39983, -97.723719)); PolygonCollection.Add(new Position(30.40182, -97.722989)); PolygonCollection.Add(new Position(30.402172, -97.724245)); PolygonCollection.Add(new Position(30.403236, -97.72374)); PolygonCollection.Add(new Position(30.402606, -97.721659)); PolygonCollection.Add(new Position(30.399562, -97.723011)); //6 original coordinates /* * // Intersection removing an interior polygon * PolygonCollection.Add(new Position(30.401807, -97.722484)); * PolygonCollection.Add(new Position(30.402455, -97.722248)); * PolygonCollection.Add(new Position(30.402561, -97.722623)); * PolygonCollection.Add(new Position(30.402302, -97.722784)); */ //TODO: look into xamarin and mvvmlight //also look into collectionchanged event?? //OnPropertyChanged("PolygonCollection"); //PolygonCollection = rockrose; }
private static IMultiPolygon FlattenMultiPolygon(IMultiPolygon mpoly, FgfGeometryFactory factory) { PolygonCollection polys = new PolygonCollection(); for (int i = 0; i < mpoly.Count; i++) { polys.Add(FlattenPolygon(mpoly[i], factory)); } return(factory.CreateMultiPolygon(polys)); }
/// <summary> /// Returns the list of polygons that are the Exclusive-OR of the two input polygons. Exclusive-OR are the regions where one polgyon /// resides but not both. /// </summary> /// <param name="polygonA">The polygon a.</param> /// <param name="polygonB">The polygon b.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> ExclusiveOr(this Polygon polygonA, Polygon polygonB, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (CLIPPER) { return(BooleanViaClipper(ClipperLib.PolyFillType.pftPositive, ClipperLib.ClipType.ctXor, new[] { polygonA }, new[] { polygonB })); } var relationship = GetPolygonInteraction(polygonA, polygonB, tolerance); return(ExclusiveOr(polygonA, polygonB, relationship, outputAsCollectionType, tolerance)); }
/// <summary> /// Returns the list of polygons that result from A-B (subtracting polygon B from polygon A). /// </summary> /// <param name="minuend">The polygon a.</param> /// <param name="subtrahend">The polygon b.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> Subtract(this Polygon minuend, Polygon subtrahend, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (CLIPPER) { return(BooleanViaClipper(ClipperLib.PolyFillType.pftPositive, ClipperLib.ClipType.ctDifference, new[] { minuend }, new[] { subtrahend })); } var polygonBInverted = subtrahend.Copy(true, true); var relationship = GetPolygonInteraction(minuend, polygonBInverted, tolerance); return(Intersect(minuend, polygonBInverted, relationship, outputAsCollectionType, tolerance)); }
// コンストラクター public LineGroupCollection(Field parent, Color color, PolygonCollection polygons) { this.Parent = parent; this.Color = color; // 多角形を作成する。 this.items = Enumerable .Range(0, polygons.Count) .Reverse() .Select(idx => new LineGroup(this, polygons[idx], this.GetTransparency(idx, polygons.Count))) .Reverse() .ToArray(); }
private void buttonLoad_Click_1(object sender, EventArgs e) { // Create a Persistence Engine. SharpGL.Persistence.PersistenceEngine engine = new SharpGL.Persistence.PersistenceEngine(); // Create a a set of polygons. PolygonCollection loaded = (PolygonCollection)engine.UserLoad(typeof(PolygonCollection)); // If we successfully loaded, set the collection. if (loaded != null) { polygons = loaded; foreach(Polygon polygon in loaded) polygon.Attributes.PolygonDrawMode = SharpGL.SceneGraph.Attributes.Polygon.PolygonMode.Lines; } }
public void UpdatePolygons() { //ObservableCollection<Position> rockrose = new ObservableCollection<Position>(); PolygonCollection.Add(new Position(30.39983, -97.723719)); PolygonCollection.Add(new Position(30.40182, -97.722989)); PolygonCollection.Add(new Position(30.402172, -97.724245)); PolygonCollection.Add(new Position(30.403236, -97.72374)); PolygonCollection.Add(new Position(30.402606, -97.721659)); PolygonCollection.Add(new Position(30.399562, -97.723011)); //TODO: look into xamarin and mvvmlight //also look into collectionchanged event?? //OnPropertyChanged("PolygonCollection"); //PolygonCollection = rockrose; }
private void buttonLoad_Click_1(object sender, EventArgs e) { // Create a Persistence Engine. SharpGL.Persistence.PersistenceEngine engine = new SharpGL.Persistence.PersistenceEngine(); // Create a a set of polygons. PolygonCollection loaded = (PolygonCollection)engine.UserLoad(typeof(PolygonCollection)); // If we successfully loaded, set the collection. if (loaded != null) { polygons = loaded; foreach (Polygon polygon in loaded) { polygon.Attributes.PolygonDrawMode = SharpGL.SceneGraph.Attributes.Polygon.PolygonMode.Lines; } } }
/// <summary> /// Returns the list of polygons that result from the subshapes common to both A and B. By providing the intersections /// between the two polygons, the operation will be performed with less time and memory. /// </summary> /// <param name="polygonA">The polygon a.</param> /// <param name="polygonB">The polygon b.</param> /// <param name="interaction">The interaction.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The minimum allowable area.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> Intersect(this Polygon polygonA, Polygon polygonB, PolygonInteractionRecord interaction, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (interaction.IntersectionWillBeEmpty()) { if (polygonB.IsPositive) { return(new List <Polygon>()); } else { return new List <Polygon> { polygonA.Copy(true, false) } }; } else { polygonIntersection ??= new PolygonIntersection(); return(polygonIntersection.Run(polygonA, polygonB, interaction, outputAsCollectionType, tolerance)); } }
/// <summary> /// Returns the list of polygons that exist in either A OR B.By providing the intersections /// between the two polygons, the operation will be performed with less time and memory. /// </summary> /// <param name="polygonA">The polygon a.</param> /// <param name="polygonB">The polygon b.</param> /// <param name="polygonInteraction">The polygon relationship.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The minimum allowable area.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> /// <exception cref="ArgumentException">A negative polygon (i.e. hole) is provided to Union which results in infinite shape. - polygonA</exception> /// <exception cref="ArgumentException">A negative polygon (i.e. hole) is provided to Union which results in infinite shape. - polygonB</exception> public static List <Polygon> Union(this Polygon polygonA, Polygon polygonB, PolygonInteractionRecord polygonInteraction, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (!polygonA.IsPositive) { throw new ArgumentException("A negative polygon (i.e. hole) is provided to Union which results in infinite shape.", nameof(polygonA)); } if (!polygonB.IsPositive) { throw new ArgumentException("A negative polygon (i.e. hole) is provided to Union which results in infinite shape.", nameof(polygonB)); } if (!polygonInteraction.CoincidentEdges && (polygonInteraction.Relationship == PolygonRelationship.Separated || polygonInteraction.Relationship == PolygonRelationship.AIsInsideHoleOfB || polygonInteraction.Relationship == PolygonRelationship.BIsInsideHoleOfA)) { return new List <Polygon> { polygonA.Copy(true, false), polygonB.Copy(true, false) } } ; if (polygonInteraction.Relationship == PolygonRelationship.BInsideA || polygonInteraction.Relationship == PolygonRelationship.Equal) { return new List <Polygon> { polygonA.Copy(true, false) } } ; if (polygonInteraction.Relationship == PolygonRelationship.AInsideB) { return new List <Polygon> { polygonB.Copy(true, false) } } ; polygonUnion ??= new PolygonUnion(); return(polygonUnion.Run(polygonA, polygonB, polygonInteraction, outputAsCollectionType, tolerance)); }
/// <summary> /// Returns the list of polygons that are the Exclusive-OR of the two input polygons. Exclusive-OR are the regions where one polgyon /// resides but not both. By providing the intersections between the two polygons, the operation will be performed with less time and memory. /// </summary> /// <param name="polygonA">The polygon a.</param> /// <param name="polygonB">The polygon b.</param> /// <param name="interactionRecord">The interaction record.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> ExclusiveOr(this Polygon polygonA, Polygon polygonB, PolygonInteractionRecord interactionRecord, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (interactionRecord.IntersectionWillBeEmpty()) { return new List <Polygon> { polygonA.Copy(true, false), polygonB.Copy(true, false) } } ; else if (interactionRecord.Relationship == PolygonRelationship.BInsideA && !interactionRecord.CoincidentEdges && !interactionRecord.CoincidentVertices) { var polygonACopy1 = polygonA.Copy(true, false); polygonACopy1.AddInnerPolygon(polygonB.Copy(true, true)); return(new List <Polygon> { polygonACopy1 }); } else if (interactionRecord.Relationship == PolygonRelationship.AInsideB && !interactionRecord.CoincidentEdges && !interactionRecord.CoincidentVertices) { var polygonBCopy2 = polygonB.Copy(true, false); polygonBCopy2.AddInnerPolygon(polygonA.Copy(true, true)); return(new List <Polygon> { polygonBCopy2 }); } else { var result = polygonA.Subtract(polygonB, interactionRecord, outputAsCollectionType, tolerance); result.AddRange(polygonB.Subtract(polygonA, interactionRecord, outputAsCollectionType, tolerance)); return(result); } }
private static IMultiPolygon FlattenMultiPolygon(IMultiPolygon mpoly, FgfGeometryFactory factory) { PolygonCollection polys = new PolygonCollection(); for (int i = 0; i < mpoly.Count; i++) { polys.Add(FlattenPolygon(mpoly[i], factory)); } return factory.CreateMultiPolygon(polys); }
/// <summary> /// All of the previous boolean operations are accomplished by this function. Note that the function RemoveSelfIntersections is also /// very simliar to this function. /// </summary> /// <param name="polygonA">The polygon a.</param> /// <param name="polygonB">The polygon b.</param> /// <param name="intersections">The intersections.</param> /// <param name="isSubtract">The switch direction.</param> /// <param name="crossProductSign">The cross product sign.</param> /// <param name="tolerance">The minimum allowable area.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> internal List <Polygon> Run(Polygon polygonA, Polygon polygonB, PolygonInteractionRecord interaction, PolygonCollection polygonCollection, double tolerance = double.NaN) { double areaTolerance; if (double.IsNaN(tolerance)) { var minDimension = Math.Min(polygonA.MaxX - polygonA.MinX, Math.Min(polygonA.MaxY - polygonA.MinY, Math.Min(polygonB.MaxX - polygonB.MinX, polygonB.MaxY - polygonB.MinY))); tolerance = Constants.BaseTolerance * minDimension; areaTolerance = tolerance * minDimension; } else { areaTolerance = tolerance * tolerance / Constants.BaseTolerance; // why change the input tolerance? here, we are using it as a } // limit on the minimum allowable area only (about 12 lines down), so in order to change it from units of length to length-squared // we need to find the characteristic length that was multiplied by the base tolerance to obtain the linear tolerance. var delimiters = NumberVerticesAndGetPolygonVertexDelimiter(polygonA); delimiters = NumberVerticesAndGetPolygonVertexDelimiter(polygonB, delimiters[^ 1]);
/// <summary> /// Returns the list of polygons that result from A-B (subtracting polygon B from polygon A). By providing the intersections /// between the two polygons, the operation will be performed with less time and memory. /// </summary> /// <param name="minuend">The polygon a.</param> /// <param name="subtrahend">The polygon b.</param> /// <param name="interaction">The polygon relationship.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> /// <exception cref="ArgumentException">The minuend is already a negative polygon (i.e. hole). Consider another operation" /// +" to accomplish this function, like Intersect. - polygonA</exception> public static List <Polygon> Subtract(this Polygon minuend, Polygon subtrahend, PolygonInteractionRecord interaction, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { interaction = interaction.InvertPolygonInRecord(subtrahend, out var invertedPolygonB); return(Intersect(minuend, invertedPolygonB, interaction, outputAsCollectionType, tolerance)); }
/// <summary> /// Returns the list of polygons that are the sub-shapes of ALL of the provided polygons. Notice this is called IntersectPolygons here /// to distinguish it from the LINQ function Intersect, which is also a valid extension for any IEnumerable collection. /// </summary> /// <param name="polygons">The polygons.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> IntersectPolygons(this IEnumerable <Polygon> polygons, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (CLIPPER) { return(BooleanViaClipper(ClipperLib.PolyFillType.pftPositive, ClipperLib.ClipType.ctIntersection, polygons)); } var polygonList = polygons.ToList(); for (int i = polygonList.Count - 2; i > 0; i--) { var clippingPoly = polygonList[i]; polygonList.RemoveAt(i); for (int j = polygonList.Count - 1; j >= i; j--) { var interaction = GetPolygonInteraction(clippingPoly, polygonList[j], tolerance); if (interaction.IntersectionWillBeEmpty()) { polygonList.RemoveAt(j); } else { var newPolygons = Intersect(clippingPoly, polygonList[j], interaction, outputAsCollectionType, tolerance); foreach (var newPolygon in newPolygons) { polygonList.Insert(j, newPolygon); } } } } return(polygonList); }
/// <summary> /// Returns the list of polygons that are the sub-shapes of the two collections of polygons. Notice this is called IntersectPolygons here /// to distinguish it from the LINQ function Intersect, which is also a valid extension for any IEnumerable collection. /// Notice also that any overlap between the polygons in A or the polygons in B are ignored. Finally, all inputs must be positive. /// /// </summary> /// <param name="polygonsA">The polygons a.</param> /// <param name="polygonsB">The polygons b.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> IntersectPolygons(this IEnumerable <Polygon> polygonsA, IEnumerable <Polygon> polygonsB, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (CLIPPER) { return(BooleanViaClipper(ClipperLib.PolyFillType.pftPositive, ClipperLib.ClipType.ctIntersection, polygonsA, polygonsB)); } var polygonAList = new List <Polygon>(polygonsA); var polygonBList = polygonsB as List <Polygon> ?? polygonsB.ToList(); if (double.IsNaN(tolerance)) { tolerance = GetTolerancesFromPolygons(polygonAList, polygonBList); } foreach (var polyB in polygonBList) { for (int i = polygonAList.Count - 1; i >= 0; i--) { var newPolygons = polygonAList[i].Intersect(polyB, outputAsCollectionType, tolerance); polygonAList.RemoveAt(i); foreach (var newPoly in newPolygons) { polygonAList.Insert(i, newPoly); } } } return(polygonAList); }
/// <summary> /// Returns the list of polygons that are the subshapes of the two collections of polygons. Notice this is called UnionPolygons /// here to distinguish it from the LINQ function Union, which is also a valid extension for any IEnumerable collection. /// </summary> /// <param name="polygonsA">The polygons a.</param> /// <param name="polygonsB">The polygons b.</param> /// <param name="outputAsCollectionType">Type of the output as collection.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Collections.Generic.List<TVGL.TwoDimensional.Polygon>.</returns> public static List <Polygon> UnionPolygons(this IEnumerable <Polygon> polygonsA, IEnumerable <Polygon> polygonsB, PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN) { if (CLIPPER) { return(BooleanViaClipper(ClipperLib.PolyFillType.pftPositive, ClipperLib.ClipType.ctUnion, polygonsA, polygonsB)); } var unionedPolygons = polygonsA.ToList(); if (polygonsB is null) { return(UnionPolygons(unionedPolygons, outputAsCollectionType, tolerance)); } var polygonBList = polygonsB.ToList(); if (double.IsNaN(tolerance)) { tolerance = GetTolerancesFromPolygons(unionedPolygons, polygonBList); } for (int i = unionedPolygons.Count - 1; i >= 0; i--) { for (int j = polygonBList.Count - 1; j >= 0; j--) { var interaction = GetPolygonInteraction(unionedPolygons[i], polygonBList[j], tolerance); if (interaction.Relationship == PolygonRelationship.BInsideA || interaction.Relationship == PolygonRelationship.Equal) { // remove polygon B polygonBList.RemoveAt(j); } else if (interaction.Relationship == PolygonRelationship.AInsideB) { // remove polygon A unionedPolygons[i] = polygonBList[j]; polygonBList.RemoveAt(j); break; // to stop the inner loop } else if (interaction.CoincidentEdges || interaction.Relationship == PolygonRelationship.Intersection) { //if (i == 1 && j == 0) //Presenter.ShowAndHang(new[] { polygonList[i], polygonList[j] }); var newPolygons = Union(unionedPolygons[i], polygonBList[j], interaction, outputAsCollectionType, tolerance); //Console.WriteLine("i = {0}, j = {1}", i, j); //if (i == 1 && j == 0) //Presenter.ShowAndHang(newPolygons); unionedPolygons.RemoveAt(i); polygonBList.RemoveAt(j); unionedPolygons.AddRange(newPolygons); i = unionedPolygons.Count; // to restart the outer loop break; // to stop the inner loop } } } return(UnionPolygons(unionedPolygons.Where(p => p.IsPositive), outputAsCollectionType, tolerance)); }