private static CoordinateSequence CreateCircularString(CoordinateSequenceFactory factory, int dimension, Coordinate center, double radius, double startAngle, int numPoints) { const int numSegmentsCircle = 48; const double angleCircle = 2 * Math.PI; const double angleStep = angleCircle / numSegmentsCircle; var sequence = factory.Create(numPoints, dimension, 0); var pm = new PrecisionModel(100); double angle = startAngle; for (int i = 0; i < numPoints; i++) { double dx = Math.Cos(angle) * radius; sequence.SetOrdinate(i, Ordinate.X, pm.MakePrecise(center.X + dx)); double dy = Math.Sin(angle) * radius; sequence.SetOrdinate(i, Ordinate.Y, pm.MakePrecise(center.Y + dy)); // set other ordinate values to predictable values for (int j = 2; j < dimension; j++) { sequence.SetOrdinate(i, j, Math.Pow(10, j - 1) * i); } angle += angleStep; angle %= angleCircle; } return(sequence); }
/// <summary> /// "Fixes" this Coordinate to the PrecisionModel grid. /// </summary> public virtual void MakePrecise(PrecisionModel precisionModel) { if (precisionModel != null) { m_dX = precisionModel.MakePrecise(m_dX); m_dY = precisionModel.MakePrecise(m_dY); } }
/// <summary> /// Get Envelope in external coordinates. /// </summary> /// <param name="precisionModel">The precision model to use</param> /// <param name="envelope">The envelope to get</param> /// <returns></returns> public static Envelope GetEnvelopeExternal(PrecisionModel precisionModel, Envelope envelope) { // Get envelope in external coordinates return(new Envelope( x1: precisionModel.MakePrecise(envelope.MinX), x2: precisionModel.MakePrecise(envelope.MaxX), y1: precisionModel.MakePrecise(envelope.MinY), y2: precisionModel.MakePrecise(envelope.MaxY))); }
/// <summary> "Fixes" this Coordinate to the PrecisionModel grid.</summary> public override void MakePrecise(PrecisionModel precisionModel) { if (precisionModel != null) { m_dX = precisionModel.MakePrecise(m_dX); m_dY = precisionModel.MakePrecise(m_dY); m_dZ = precisionModel.MakePrecise(m_dZ); } }
private static ICoordinateSequence CreateRandomTestSequence(ICoordinateSequenceFactory csFactory, int size, int dim, Random rnd, Envelope range, PrecisionModel pm) { var cs = csFactory.Create(size, dim); for (int i = 0; i < size; i++) { cs.SetOrdinate(i, Ordinate.X, pm.MakePrecise(range.Width * rnd.NextDouble() + range.MinX)); cs.SetOrdinate(i, Ordinate.Y, pm.MakePrecise(range.Height * rnd.NextDouble() + range.MinY)); } return(FillNonPlanarDimensions(cs)); }
private Coordinate Round(Coordinate pt) { var p2 = pt.Copy(); _pm.MakePrecise(p2); return(p2); }
private Point CopyPoint(Point pt) { // if pm is floating, the point coordinate is not changed if (OverlayUtility.IsFloating(_pm)) { return((Point)pt.Copy()); } // pm is fixed. Round off X&Y ordinates, copy other ordinates unchanged var seq = pt.CoordinateSequence; var seq2 = seq.Copy(); seq2.SetOrdinate(0, Ordinate.X, _pm.MakePrecise(seq.GetX(0))); seq2.SetOrdinate(0, Ordinate.Y, _pm.MakePrecise(seq.GetY(0))); return(_geometryFactory.CreatePoint(seq2)); }
/// <summary> /// Computes the centroid based on both the shell and the holes. /// </summary> /// <exception cref="System.InvalidOperationException"> /// The number of coordinates in less than 3. /// or /// The coordinates do not represent a surface. /// </exception> protected void ComputeForShellAndHoles() { Double resultX = 0, resultY = 0, resultZ = 0; _area = 0; _baseCoordinate = _shell[0]; resultZ = _shell[0].Z; AddCoordinates(_shell, 1, ref resultX, ref resultY); foreach (IList <Coordinate> hole in _holes) { if (hole == null) { continue; } AddCoordinates(hole, -1, ref resultX, ref resultY); } resultX = resultX / 3 / _area; resultY = resultY / 3 / _area; _result = PrecisionModel.MakePrecise(new Coordinate(resultX, resultY, resultZ)); _hasResult = true; }
/// <summary> /// Sets the coordinate at the specified index. /// </summary> /// <param name="index">The zero-based index of the coordinate to set.</param> /// <param name="coordinate">The coordinate.</param> /// <exception cref="System.ArgumentOutOfRangeException"> /// The index is less than 0. /// or /// Index is equal to or greater than the number of coordinates. /// </exception> public override void SetCoordinate(Int32 index, Coordinate coordinate) { if (index < 0) { throw new ArgumentOutOfRangeException("index", "The index is less than 0."); } if (index >= _coordinates.Count) { throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than the number of coordinates."); } if (_coordinates[index].Equals(coordinate)) { return; } if (index == 0 || index == _coordinates.Count - 1) { _coordinates[0] = PrecisionModel.MakePrecise(coordinate); _coordinates[_coordinates.Count - 1] = _coordinates[0]; } else { _coordinates[index] = PrecisionModel.MakePrecise(coordinate); } OnGeometryChanged(); }
/// <summary> /// Densifies a coordinate sequence. /// </summary> /// <param name="pts">The coordinate sequence to densify</param> /// <param name="distanceTolerance">The distance tolerance (<see cref="DistanceTolerance"/>)</param> /// <param name="precModel">The precision model to apply on the new coordinates</param> /// <returns>The densified coordinate sequence</returns> private static Coordinate[] DensifyPoints(Coordinate[] pts, double distanceTolerance, PrecisionModel precModel) { var seg = new LineSegment(); var coordList = new CoordinateList(); for (int i = 0; i < pts.Length - 1; i++) { seg.P0 = pts[i]; seg.P1 = pts[i + 1]; coordList.Add(seg.P0, false); double len = seg.Length; int densifiedSegCount = (int)(len / distanceTolerance) + 1; if (densifiedSegCount > 1) { double densifiedSegLen = len / densifiedSegCount; for (int j = 1; j < densifiedSegCount; j++) { double segFract = (j * densifiedSegLen) / len; var p = seg.PointAlong(segFract); precModel.MakePrecise(p); coordList.Add(p, false); } } } coordList.Add(pts[pts.Length - 1], false); return(coordList.ToCoordinateArray()); }
/// <summary> /// /// </summary> /// <param name="tokens"></param> /// <param name="skipExtraParenthesis"></param> /// <returns></returns> private Coordinate GetPreciseCoordinate(IList tokens, Boolean skipExtraParenthesis) { var coord = new CoordinateZM(); Boolean extraParenthesisFound = false; if (skipExtraParenthesis) { extraParenthesisFound = IsStringValueNext(tokens, "("); //NOXLATE if (extraParenthesisFound) { index++; } } coord.X = GetNextNumber(tokens); coord.Y = GetNextNumber(tokens); if (IsNumberNext(tokens)) { coord.Z = GetNextNumber(tokens); } if (IsNumberNext(tokens)) { coord.M = GetNextNumber(tokens); } if (skipExtraParenthesis && extraParenthesisFound && IsStringValueNext(tokens, ")")) //NOXLATE { index++; } precisionModel.MakePrecise((Coordinate)coord); return(coord); }
/// <summary> /// Computes the centroid based on the shell. /// </summary> /// <exception cref="System.InvalidOperationException"> /// The number of coordinates in less than 3. /// or /// The coordinates do not represent a surface. /// </exception> protected void ComputeForShell() { Double resultX = 0, resultY = 0; _area = 0; if (_shell.Count < 3) // if there are not enough coordinates { _hasResult = true; return; } for (Int32 i = 0; i < _shell.Count - 1; i++) { resultX += (_shell[i].X + _shell[i + 1].X) * (_shell[i].X * _shell[i + 1].Y - _shell[i + 1].X * _shell[i].Y); resultY += (_shell[i].Y + _shell[i + 1].Y) * (_shell[i].X * _shell[i + 1].Y - _shell[i + 1].X * _shell[i].Y); _area += _shell[i].X * _shell[i + 1].Y - _shell[i + 1].X * _shell[i].Y; } _area /= 2; resultX /= (6 * _area); resultY /= (6 * _area); _result = PrecisionModel.MakePrecise(new Coordinate(resultX, resultY, _shell[0].Z)); _hasResult = true; }
private Coordinate[] ReduceCompress(CoordinateSequence coordinates) { var noRepeatCoordList = new CoordinateList(); // copy coordinates and reduce for (int i = 0; i < coordinates.Count; i++) { var coord = coordinates.GetCoordinate(i).Copy(); _targetPm.MakePrecise(coord); noRepeatCoordList.Add(coord, false); } // remove repeated points, to simplify returned geometry as much as possible var noRepeatCoords = noRepeatCoordList.ToCoordinateArray(); return(noRepeatCoords); }
/// <summary> /// Writes a single coordinate to JSON /// </summary> /// <param name="writer">The writer</param> /// <param name="coordinate">The coordinate</param> protected void WriteJsonCoordinate(JsonWriter writer, Coordinate coordinate) { writer.WriteStartArray(); double value = _precisionModel.MakePrecise(coordinate.X); writer.WriteValue(value); value = _precisionModel.MakePrecise(coordinate.Y); writer.WriteValue(value); if (_dimension > 2 && !double.IsNaN(coordinate.Z)) { writer.WriteValue(coordinate.Z); } writer.WriteEndArray(); }
public override Coordinate[] Edit(Coordinate[] coordinates, Geometry geom) { if (coordinates.Length == 0) { return(null); } var reducedCoords = new Coordinate[coordinates.Length]; // copy coordinates and reduce for (int i = 0; i < coordinates.Length; i++) { var coord = coordinates[i].Copy(); _targetPrecModel.MakePrecise(coord); reducedCoords[i] = coord; } // remove repeated points, to simplify returned geometry as much as possible var noRepeatedCoordList = new CoordinateList(reducedCoords, false); var noRepeatedCoords = noRepeatedCoordList.ToCoordinateArray(); /** * Check to see if the removal of repeated points collapsed the coordinate * List to an invalid length for the type of the parent geometry. It is not * necessary to check for Point collapses, since the coordinate list can * never collapse to less than one point. If the length is invalid, return * the full-length coordinate array first computed, or null if collapses are * being removed. (This may create an invalid geometry - the client must * handle this.) */ int minLength = 0; if (geom is LineString) { minLength = 2; } if (geom is LinearRing) { minLength = LinearRing.MinimumValidSize; } var collapsedCoords = reducedCoords; if (_removeCollapsed) { collapsedCoords = null; } // return null or original length coordinate array if (noRepeatedCoords.Length < minLength) { return(collapsedCoords); } // ok to return shorter coordinate array return(noRepeatedCoords); }
private Coordinate MakePrecise(Coordinate coord) { if (_precModel == null) { return(coord); } _precModel.MakePrecise(coord); return(coord); }
private Coordinate computePoint(LineSegment seg, double dist) { double dx = seg.P1.X - seg.P0.X; double dy = seg.P1.Y - seg.P0.Y; double len = seg.Length; var pt = new Coordinate(dist * dx / len, dist * dy / len); pm.MakePrecise(pt); return(pt); }
/// <summary> /// Reads a <see cref="CoordinateSequence"/> from the stream /// </summary> /// <param name="reader">The binary reader</param> /// <param name="factory">The geometry factory to use for geometry creation.</param> /// <param name="precisionModel">The precision model used to make x- and y-ordinates precise.</param> /// <param name="numPoints">The number of points in the coordinate sequence.</param> /// <param name="receivedOrdinates">The ordinates to read. <see cref="Ordinates.XY"/> are always read.</param> /// <returns>The coordinate sequence</returns> protected CoordinateSequence ReadCoordinateSequence(BinaryReader reader, CoordinateSequenceFactory factory, PrecisionModel precisionModel, int numPoints, Ordinates receivedOrdinates) { var outputOrdinates = receivedOrdinates; if (HandleOrdinates != Ordinates.None) { outputOrdinates &= HandleOrdinates; } var sequence = factory.Create(numPoints, outputOrdinates); bool receivedZ = receivedOrdinates.HasFlag(Ordinates.Z); bool receivedM = receivedOrdinates.HasFlag(Ordinates.M); bool outputtingZ = outputOrdinates.HasFlag(Ordinates.Z) && sequence.HasZ; bool outputtingM = outputOrdinates.HasFlag(Ordinates.M) && sequence.HasM; for (int i = 0; i < numPoints; i++) { sequence.SetX(i, precisionModel.MakePrecise(reader.ReadDouble())); sequence.SetY(i, precisionModel.MakePrecise(reader.ReadDouble())); if (receivedZ) { double z = reader.ReadDouble(); if (outputtingZ) { sequence.SetZ(i, z); } } if (receivedM) { double m = reader.ReadDouble(); if (outputtingM) { sequence.SetM(i, m); } } } return(sequence); }
private static double RandomOrdinate(Ordinate o, PrecisionModel pm) { switch (o) { case Ordinate.X: return(pm.MakePrecise(-180 + 360 * Rnd.NextDouble())); case Ordinate.Y: return(pm.MakePrecise(-90 + 180 * Rnd.NextDouble())); case Ordinate.Z: return(200 * Rnd.NextDouble()); case Ordinate.M: return(200 + 200 * Rnd.NextDouble()); default: throw new NotSupportedException(); } }
/// <summary> /// Inserts a coordinate into the linear ring at the specified index. /// </summary> /// <param name="index">The zero-based index at which the coordinate should be inserted.</param> /// <param name="coordinate">The coordinate.</param> /// <exception cref="System.ArgumentOutOfRangeException"> /// The index is less than 0. /// or /// Index is greater than the number of coordinates. /// </exception> public override void Insert(Int32 index, Coordinate coordinate) { if (index == 0) // insertion of new starting coordinate { _coordinates[_coordinates.Count - 1] = PrecisionModel.MakePrecise(coordinate); base.Insert(0, coordinate); } else // insertion of new inner coordinate { base.Insert(index, PrecisionModel.MakePrecise(coordinate)); } }
private static void PreciseCoordinateTester(PrecisionModel pm, double x1, double y1, double x2, double y2) { var p = new Coordinate(x1, y1); pm.MakePrecise(p); var pPrecise = new Coordinate(x2, y2); Assert.IsTrue(p.Equals2D(pPrecise), "Expected {0}, but got {1}", pPrecise, p); }
/// <summary> /// Add a hole to the polygon. /// </summary> /// <param name="hole">The hole.</param> /// <exception cref="System.ArgumentNullException">The hole is null.</exception> public virtual void AddHole(IEnumerable <Coordinate> hole) { if (hole == null) { throw new ArgumentNullException("hole", "The hole is null."); } _holes.Add(Factory.CreateLinearRing(hole.Select(coordinate => PrecisionModel.MakePrecise(coordinate)))); _holes[_holes.Count - 1].GeometryChanged += new EventHandler(Hole_GeometryChanged); // add event handler OnGeometryChanged(); }
/// <summary> /// This method computes the actual value of the intersection point. /// To obtain the maximum precision from the intersection calculation, /// the coordinates are normalized by subtracting the minimum /// ordinate values (in absolute value). This has the effect of /// removing common significant digits from the calculation to /// maintain more bits of precision. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="q1"></param> /// <param name="q2"></param> /// <returns></returns> private Coordinate Intersection(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { Coordinate n1 = new Coordinate(p1); Coordinate n2 = new Coordinate(p2); Coordinate n3 = new Coordinate(q1); Coordinate n4 = new Coordinate(q2); Coordinate normPt = new Coordinate(); NormalizeToEnvCentre(n1, n2, n3, n4, normPt); Coordinate intPt = HCoordinate.Intersection(n1, n2, n3, n4); intPt.X += normPt.X; intPt.Y += normPt.Y; /* * * MD - May 4 2005 - This is still a problem. Here is a failure case: * * LINESTRING (2089426.5233462777 1180182.3877339689, 2085646.6891757075 1195618.7333999649) * LINESTRING (1889281.8148903656 1997547.0560044837, 2259977.3672235999 483675.17050843034) * int point = (2097408.2633752143, 1144595.8008114607) */ if (!IsInSegmentEnvelopes(intPt)) { Trace.WriteLine("Intersection outside segment envelopes: " + intPt); } /* * // disabled until a better solution is found * if (!IsInSegmentEnvelopes(intPt)) * { * Trace.WriteLine("first value outside segment envelopes: " + intPt); * * IteratedBisectionIntersector ibi = new IteratedBisectionIntersector(p1, p2, q1, q2); * intPt = ibi.Intersection; * } * if (!IsInSegmentEnvelopes(intPt)) * { * Trace.WriteLine("ERROR - outside segment envelopes: " + intPt); * * IteratedBisectionIntersector ibi = new IteratedBisectionIntersector(p1, p2, q1, q2); * Coordinate testPt = ibi.Intersection; * } */ if (PrecisionModel != null) { PrecisionModel.MakePrecise(intPt); } return(intPt); }
public void PrecisionModelMakePreciseTest() { for (Int32 i = 0; i < _values.Length; i++) { Assert.AreEqual(_values[i], _defaultModel.MakePrecise(_values[i])); Assert.AreEqual(_values[i], _floatingModel.MakePrecise(_values[i])); Assert.AreEqual((Single)_values[i], _floatingSingleModel.MakePrecise(_values[i])); Assert.AreEqual(Math.Round(_values[i], 3), _fixedLargeModel1.MakePrecise(_values[i])); Assert.AreEqual(Math.Round(_values[i], 12), _fixedLargeModel2.MakePrecise(_values[i])); Assert.AreEqual(Math.Round(_values[i] / 1000) * 1000, _fixedSmallModel1.MakePrecise(_values[i])); Assert.AreEqual(Math.Round(_values[i] / 1000000000000) * 1000000000000, _fixedSmallModel2.MakePrecise(_values[i])); } }
/// <summary> /// Round the key point if precision model is fixed. /// Note: return value is only copied if rounding is performed. /// </summary> static Coordinate RoundCoord(Point pt, PrecisionModel pm) { var p = pt.Coordinate; if (pm.IsFloating) { return(p); } var p2 = p.Copy(); pm.MakePrecise(p2); return(p2); }
/// <summary> /// /// </summary> /// <param name="tokens"></param> /// <returns></returns> private Coordinate GetPreciseCoordinate(IList tokens) { Coordinate coord = new Coordinate(); coord.X = GetNextNumber(tokens); coord.Y = GetNextNumber(tokens); if (IsNumberNext(tokens)) { coord.Z = GetNextNumber(tokens); } precisionModel.MakePrecise(coord); return(coord); }
/// <summary> /// Initializes a new instance of the <see cref="LineString" /> class. /// </summary> /// <param name="source">The source coordinates.</param> /// <param name="factory">The factory of the line string.</param> /// <param name="metadata">The metadata.</param> /// <exception cref="System.ArgumentNullException"> /// The source is null. /// or /// The factory is null. /// </exception> /// <exception cref="System.ArgumentException">The specified factory is invalid.</exception> public LineString(IEnumerable <Coordinate> source, IGeometryFactory factory, IDictionary <String, Object> metadata) : base(factory, metadata) { if (source == null) { _coordinates = new List <Coordinate>(); } else { _coordinates = new List <Coordinate>(source.Select(coordinate => PrecisionModel.MakePrecise(coordinate))); } _version = 0; }
/// <summary> /// Round the key point if precision model is fixed. /// Note: return value is only copied if rounding is performed. /// </summary> /// <param name="pt">The point to round</param> /// <param name="pm">The precision model to use</param> /// <returns>The rounded point coordinate, or null if empty</returns> public static Coordinate Round(Point pt, PrecisionModel pm) { if (pt.IsEmpty) { return(null); } var p = pt.Coordinate.Copy(); if (!pm.IsFloating) { pm.MakePrecise(p); } return(p); }
private static Coordinate[] CreateCircularString(Coordinate center, double radius, double startAngle, int numPoints) { const int numSegmentsCircle = 48; const double angleCircle = 2 * Math.PI; const double angleStep = angleCircle / numSegmentsCircle; var sequence = new Coordinate[numPoints]; var pm = new PrecisionModel(1000); double angle = startAngle; for (int i = 0; i < numPoints; i++) { double dx = Math.Cos(angle) * radius; double dy = Math.Sin(angle) * radius; sequence[i] = new Coordinate(pm.MakePrecise(center.X + dx), pm.MakePrecise(center.Y + dy)); angle += angleStep; angle %= angleCircle; } return(sequence); }
private void CheckLine45(int width, int nPts, double precision) { var p1 = new Coordinate(0, width); var p2 = new Coordinate(width, 0); for (int i = 0; i <= nPts; i++) { double d = width / (double)nPts; var q = new Coordinate(0.0 + i * d, width - i * d); var pm = new PrecisionModel(precision); pm.MakePrecise(q); CheckPointOnSeg(p1, p2, q); } }