/// <summary> /// Add a <c>LineString</c> forming an edge of the polygon graph. /// </summary> /// <param name="line">The line to add.</param> public void AddEdge(ILineString line) { if (line.IsEmpty) { return; } ICoordinate[] linePts = CoordinateArrays.RemoveRepeatedPoints(line.Coordinates); ICoordinate startPt = linePts[0]; ICoordinate endPt = linePts[linePts.Length - 1]; Node nStart = GetNode(startPt); Node nEnd = GetNode(endPt); DirectedEdge de0 = new PolygonizeDirectedEdge(nStart, nEnd, linePts[1], true); DirectedEdge de1 = new PolygonizeDirectedEdge(nEnd, nStart, linePts[linePts.Length - 2], false); Edge edge = new PolygonizeEdge(line); edge.SetDirectedEdges(de0, de1); Add(edge); }
public void TestScroll() { // arrange var sequence = CreateCircularString(new Coordinate(20, 20), 7d, 0.1, 22); var scrolled = CreateCircularString(new Coordinate(20, 20), 7d, 0.1, 22);; // act CoordinateArrays.Scroll(scrolled, 12); // assert int io = 12; for (int isc = 0; isc < scrolled.Length - 1; isc++) { CheckCoordinateAt(sequence, io, scrolled, isc); io++; io %= scrolled.Length; } }
public void TestEqualsInHashBasedCollection() { var p0 = new Coordinate(0, 0); var p1 = new Coordinate(0, 1); var p2 = new Coordinate(1, 0); Coordinate[] exactEqualRing1 = { p0, p1, p2, p0 }; var exactEqualRing2 = CoordinateArrays.CopyDeep(exactEqualRing1); Coordinate[] rotatedRing1 = { p1, p2, p0, p1 }; Coordinate[] rotatedRing2 = { p2, p0, p1, p2 }; var exactEqualRing1Poly = geometryFactory.CreatePolygon(exactEqualRing1); var exactEqualRing2Poly = geometryFactory.CreatePolygon(exactEqualRing2); var rotatedRing1Poly = geometryFactory.CreatePolygon(rotatedRing1); var rotatedRing2Poly = geometryFactory.CreatePolygon(rotatedRing2); // IGeometry equality in hash-based collections should be based on // EqualsExact semantics, as it is in JTS. var hashSet1 = new HashSet <IGeometry> { exactEqualRing1Poly, exactEqualRing2Poly, rotatedRing1Poly, rotatedRing2Poly, }; Assert.AreEqual(3, hashSet1.Count); // same as IPolygon equality. var hashSet2 = new HashSet <IPolygon> { exactEqualRing1Poly, exactEqualRing2Poly, rotatedRing1Poly, rotatedRing2Poly, }; Assert.AreEqual(3, hashSet2.Count); }
/// <summary> /// The left and right topological location arguments assume that the ring is oriented CW. /// If the ring is in the opposite orientation, /// the left and right locations must be interchanged. /// </summary> /// <param name="lr"></param> /// <param name="cwLeft"></param> /// <param name="cwRight"></param> private void AddPolygonRing(ILinearRing lr, Locations cwLeft, Locations cwRight) { ICoordinate[] coord = CoordinateArrays.RemoveRepeatedPoints(lr.Coordinates); if (coord.Length < 4) { hasTooFewPoints = true; invalidPoint = coord[0]; return; } Locations left = cwLeft; Locations right = cwRight; if (CGAlgorithms.IsCCW(coord)) { left = cwRight; right = cwLeft; } Edge e = new Edge(coord, new Label(argIndex, Locations.Boundary, left, right)); lineEdgeMap[lr] = e; InsertEdge(e); // insert the endpoint as a node, to mark that it is on the boundary InsertPoint(argIndex, coord[0], Locations.Boundary); }
public static Geometry FindNodes(Geometry geom) { var intPts = FastNodingValidator.ComputeIntersections(SegmentStringUtil.ExtractNodedSegmentStrings(geom)); return(FunctionsUtil.GetFactoryOrDefault((Geometry)null).CreateMultiPointFromCoords(CoordinateArrays.ToCoordinateArray(intPts))); }
private void ComputeCirclePoints() { Coordinate[] pts; // handle degenerate or trivial cases if (_input.IsEmpty) { _extremalPts = new Coordinate[0]; return; } if (_input.NumPoints == 1) { pts = _input.Coordinates; _extremalPts = new[] { new Coordinate(pts[0]) }; return; } /** * The problem is simplified by reducing to the convex hull. * Computing the convex hull also has the useful effect of eliminating duplicate points */ var convexHull = _input.ConvexHull(); // check for degenerate or trivial cases var hullPts = convexHull.Coordinates; // strip duplicate final point, if any pts = hullPts; if (hullPts[0].Equals2D(hullPts[hullPts.Length - 1])) { pts = new Coordinate[hullPts.Length - 1]; CoordinateArrays.CopyDeep(hullPts, 0, pts, 0, hullPts.Length - 1); } /** * Optimization for the trivial case where the CH has fewer than 3 points */ if (pts.Length <= 2) { _extremalPts = CoordinateArrays.CopyDeep(pts); return; } // find a point P with minimum Y ordinate var P = LowestPoint(pts); // find a point Q such that the angle that PQ makes with the x-axis is minimal var Q = PointWitMinAngleWithX(pts, P); /** * Iterate over the remaining points to find * a pair or triplet of points which determine the minimal circle. * By the design of the algorithm, * at most <tt>pts.length</tt> iterations are required to terminate * with a correct result. */ for (int i = 0; i < pts.Length; i++) { var R = PointWithMinAngleWithSegment(pts, P, Q); // if PRQ is obtuse, then MBC is determined by P and Q if (AngleUtility.IsObtuse(P, R, Q)) { _extremalPts = new Coordinate[] { new Coordinate(P), new Coordinate(Q) }; return; } // if RPQ is obtuse, update baseline and iterate if (AngleUtility.IsObtuse(R, P, Q)) { P = R; continue; } // if RQP is obtuse, update baseline and iterate if (AngleUtility.IsObtuse(R, Q, P)) { Q = R; continue; } // otherwise all angles are acute, and the MBC is determined by the triangle PQR _extremalPts = new Coordinate[] { new Coordinate(P), new Coordinate(Q), new Coordinate(R) }; return; } Assert.ShouldNeverReachHere("Logic failure in Minimum Bounding Circle algorithm!"); }
public void ExtractTest2() { Coordinate[] result = CoordinateArrays.Extract(array, 1, 10); Assert.IsNull(result); }
public void TestIntersection_coords_emptyEnvelope() { Assert.IsTrue(CoordinateArrays.Equals( CoordinateArrays.Intersection(Coords1, new Envelope()), Empty) ); }
/// <summary> /// Constructs a sequence based on the given array of <see cref="Coordinate"/>s. /// The coordinate dimension defaults to 2 /// </summary> /// <remarks> /// The array is not copied. /// </remarks> /// <param name="coordinates">The coordinate array that will be referenced.</param> public CoordinateArraySequence(Coordinate[] coordinates) : this(coordinates, CoordinateArrays.Dimension(coordinates), CoordinateArrays.Measures(coordinates)) { }
/* * (non-Javadoc) * * @see org.hibernatespatial.mgeom.IMGeometry#GetCoordinatesBetween(double,double) */ public ICoordinateSequence[] GetCoordinatesBetween(double fromM, double toM) { if (!this.IsMonotone(false)) { throw new ApplicationException("MGeometryException.OPERATION_REQUIRES_MONOTONE"); } if (this.IsEmpty || !this.IsMonotone(false)) { return(new MCoordinateSequence[0]); } else { double[] mval = this.GetMeasures(); // determin upper and lower boundaries for the MLineString Measures double lb = Math.Min(mval[0], mval[mval.Length - 1]); double up = Math.Max(mval[0], mval[mval.Length - 1]); // set fromM and toM to maximal/minimal values when they exceed // lowerbound-upperbound fromM = Math.Max(lb, Math.Min(fromM, up)); toM = Math.Max(lb, Math.Min(toM, up)); // if at this point the fromM and toM are equal, then return an // empty MCoordinateSequence if (DoubleComparator.Equals(fromM, toM)) { return(new MCoordinateSequence[0]); } MCoordinate[] mcoords = (MCoordinate[])this.Coordinates; // ensure that we traverse the coordinate array in ascending M-order if (GetMeasureDirection() == MGeometryType.Decreasing) { CoordinateArrays.Reverse(mcoords); } double minM = Math.Min(fromM, toM); double maxM = Math.Max(fromM, toM); List <MCoordinate> mcolist = new List <MCoordinate>(); for (int i = 0; i < mcoords.Length; i++) { if (mcolist.Count == 0 && mcoords[i].M >= minM) { MCoordinate mco2 = mcoords[i]; if (DoubleComparator.Equals(mcoords[i].M, minM)) { mcolist.Add(mco2); } else { MCoordinate mco1 = mcoords[i - 1]; double r = (minM - mco1.M) / (mco2.M - mco1.M); Debug.Assert(DoubleComparator.Equals(mco1.M + r * (mco2.M - mco1.M), minM), "Error on assumption on r"); MCoordinate mc = new MCoordinate( mco1.X + r * (mco2.X - mco1.X), mco1.Y + r * (mco2.Y - mco1.Y), mco1.Z + r * (mco2.Z - mco1.Z), minM); mcolist.Add(mc); } } else if (mcoords[i].M >= minM && mcoords[i].M <= maxM) { mcolist.Add(mcoords[i]); if (DoubleComparator.Equals(mcoords[i].M, maxM)) { break; } } else if (mcoords[i].M > maxM) { // mcoords[i] > Math.max(fromM, toM Debug.Assert(i > 0, "mistaken assumption"); MCoordinate mco2 = mcoords[i]; MCoordinate mco1 = mcoords[i - 1]; double r = (maxM - mco1.M) / (mco2.M - mco1.M); MCoordinate mc = new MCoordinate( mco1.X + r * (mco2.X - mco1.X), mco1.Y + r * (mco2.Y - mco1.Y), mco1.Z + r * (mco2.Z - mco1.Z), maxM ); mcolist.Add(mc); break; } } // copy over, but only to the length of numPnts MCoordinate[] h = new MCoordinate[mcolist.Count]; for (int i = 0; i < mcolist.Count; i++) { h[i] = (MCoordinate)mcolist[i]; } if (!DoubleComparator.Equals(minM, fromM)) { CoordinateArrays.Reverse(h); } MCoordinateSequence mc2 = new MCoordinateSequence(h); return(new MCoordinateSequence[] { mc2 }); } }
public void TestEnvelopeEmpty() { Assert.AreEqual(CoordinateArrays.Envelope(Empty), new Envelope()); }
public void TestEnvelope1() { Assert.AreEqual(CoordinateArrays.Envelope(Coords1), new Envelope(1, 3, 1, 3)); }
/// <summary> /// Constructs a sequence based on the given array /// of <see cref="Coordinate"/>s. /// </summary> /// <remarks>The Array is not copied</remarks> /// <param name="coordinates">The coordinate array that will be referenced.</param> /// <param name="dimension">The dimension of the coordinates</param> public CoordinateArraySequence(Coordinate[] coordinates, int dimension) : this(coordinates, dimension, CoordinateArrays.Measures(coordinates)) { }
/// <summary> /// Sets the sites (point or vertices) which will be diagrammed /// from a collection of <see cref="Coordinate"/>s. /// </summary> /// <param name="coords">a collection of Coordinates.</param> public void SetSites(ICollection <Coordinate> coords) { // remove any duplicate points (they will cause the triangulation to fail) _siteCoords = DelaunayTriangulationBuilder.Unique(CoordinateArrays.ToCoordinateArray(coords)); }
public void TestIntersection_envelopeDisjoint() { Assert.IsTrue(CoordinateArrays.Equals( CoordinateArrays.Intersection(Coords1, new Envelope(10, 20, 10, 20)), Empty) ); }
/// <summary> /// Computes the canonical orientation for a coordinate array. /// </summary> /// <param name="pts"></param> /// <returns> /// <c>true</c> if the points are oriented forwards <br/> /// or <c>false</c>if the points are oriented in reverse. /// </returns> private static bool Orientation(Coordinate[] pts) { return(CoordinateArrays.IncreasingDirection(pts) == 1); }
public void TestIntersection_empty_envelope() { Assert.IsTrue(CoordinateArrays.Equals( CoordinateArrays.Intersection(Empty, new Envelope(1, 2, 1, 2)), Empty) ); }
/// <summary> /// Computes the canonical orientation for a coordinate array. /// </summary> /// <param name="pts"></param> /// <returns> /// <c>true</c> if the points are oriented forwards, or /// <c>false</c>if the points are oriented in reverse. /// </returns> private static bool Orientation(IList<Coordinate> pts) { return CoordinateArrays.IncreasingDirection(pts) == 1; }
public static IGeometry FindNodePoints(IGeometry geom) { IList <Coordinate> intPts = FastNodingValidator.ComputeIntersections(SegmentStringUtil.ExtractNodedSegmentStrings(geom)); return(FunctionsUtil.GetFactoryOrDefault(null).CreateMultiPoint(CoordinateArrays.ToCoordinateArray(intPts))); }