/// <summary> /// Creates a Point using the next token in the stream. /// </summary> /// <param name="tokenizer"> /// Tokenizer over a stream of text in Well-known Text /// format. The next tokens must form a <Point Text>. /// </param> /// <returns> /// Returns a Point specified by the next token in /// the stream. /// </returns> /// <remarks> /// ParseException is thrown if an unexpected token is encountered. /// </remarks> private static MapPoint ReadPointText(WktStreamTokenizer tokenizer) { var nextToken = GetNextEmptyOrOpener(tokenizer); if (nextToken == "EMPTY") { throw new Exception("Empty Point"); } var p = new MapPoint(GetNextNumber(tokenizer), GetNextNumber(tokenizer)); GetNextCloser(tokenizer); return(p); }
/// <summary> /// Creates a <see cref="Polyline" /> using the next token in the stream. /// </summary> /// <param name="tokenizer"> /// tokenizer over a stream of text in Well-known Text format. The next tokens must form a /// MultiLineString Text /// </param> /// <returns>a <see cref="Polyline" /> specified by the next token in the stream</returns> private static Polyline ReadMultiLineStringText(WktStreamTokenizer tokenizer) { var nextToken = GetNextEmptyOrOpener(tokenizer); if (nextToken == "EMPTY") { throw new Exception("Empty Multiline"); } var lines = new PolylineBuilder(GetCoordinates(tokenizer)); nextToken = GetNextCloserOrComma(tokenizer); while (nextToken == ",") { lines.AddPart(GetCoordinates(tokenizer)); nextToken = GetNextCloserOrComma(tokenizer); } return(lines.ToGeometry()); }
/// <summary> /// Creates a Polygon using the next token in the stream. /// </summary> /// <param name="tokenizer"> /// Tokenizer over a stream of text in Well-known Text /// format. The next tokens must form a <Polygon Text>. /// </param> /// <param name="exteriorRingCcw"></param> /// <param name="exteriorRingCcwSpecified"></param> /// <returns> /// Returns a Polygon specified by the next token /// in the stream /// </returns> /// <remarks> /// ParseException is thown if the coordinates used to create the Polygon /// shell and holes do not form closed linestrings, or if an unexpected /// token is encountered. /// </remarks> private static Polygon ReadPolygonText(WktStreamTokenizer tokenizer, bool exteriorRingCcw = false, bool exteriorRingCcwSpecified = false) { var nextToken = GetNextEmptyOrOpener(tokenizer); if (nextToken == "EMPTY") { throw new Exception("Empty Polygon"); } var exteriorRing = GetCoordinates(tokenizer); IEnumerable <MapPoint> firstRing; // Exterior ring. Force it to be CW/CCW to match the first exterior ring of the multipolygon, if it is part of a multipolygon if (exteriorRingCcwSpecified) { firstRing = Algorithms.IsCcw(exteriorRing) != exteriorRingCcw?Reverse(exteriorRing) : exteriorRing; } else { firstRing = exteriorRing; } var polygonBuilder = new PolygonBuilder(firstRing); nextToken = GetNextCloserOrComma(tokenizer); while (nextToken == ",") { //Add holes var interiorRing = GetCoordinates(tokenizer); var correctedRing = interiorRing; // Make sure interior rings go in the opposite direction of the exterior rings if (Algorithms.IsCcw(interiorRing) == exteriorRingCcw) { correctedRing = Reverse(interiorRing); } polygonBuilder.AddPart(correctedRing); //interior rings nextToken = GetNextCloserOrComma(tokenizer); } return(polygonBuilder.ToGeometry()); }
/// <summary> /// Returns the next array of Coordinates in the stream. /// </summary> /// <param name="tokenizer"> /// Tokenizer over a stream of text in Well-known Text format. The /// next element returned by the stream should be "(" (the beginning of "(x1 y1, x2 y2, ..., xn yn)" or /// "EMPTY". /// </param> /// <returns> /// The next array of Coordinates in the stream, or an empty array of "EMPTY" is the /// next element returned by the stream. /// </returns> private static IEnumerable <MapPoint> GetCoordinates(WktStreamTokenizer tokenizer) { var coordinates = new PointCollection(); var nextToken = GetNextEmptyOrOpener(tokenizer); if (nextToken == "EMPTY") { return(coordinates); } var externalCoordinate = new MapPoint(GetNextNumber(tokenizer), GetNextNumber(tokenizer)); coordinates.Add(externalCoordinate); nextToken = GetNextCloserOrComma(tokenizer); while (nextToken == ",") { var internalCoordinate = new MapPoint(GetNextNumber(tokenizer), GetNextNumber(tokenizer)); coordinates.Add(internalCoordinate); nextToken = GetNextCloserOrComma(tokenizer); } return(coordinates); }
/// <summary> /// Returns the next number in the stream. /// </summary> /// <param name="tokenizer"> /// Tokenizer over a stream of text in Well-known text format. The next token /// must be a number. /// </param> /// <returns>Returns the next number in the stream.</returns> /// <remarks> /// ParseException is thrown if the next token is not a number. /// </remarks> private static double GetNextNumber(WktStreamTokenizer tokenizer) { tokenizer.NextToken(); return(tokenizer.GetNumericValue()); }
/// <summary> /// Creates a LineString using the next token in the stream. /// </summary> /// <param name="tokenizer"> /// Tokenizer over a stream of text in Well-known Text format. The next /// tokens must form a LineString Text. /// </param> /// <returns>Returns a LineString specified by the next token in the stream.</returns> /// <remarks> /// ParseException is thrown if an unexpected token is encountered. /// </remarks> private static Polyline ReadLineStringText(WktStreamTokenizer tokenizer) { return(new Polyline(GetCoordinates(tokenizer))); }
/// <summary> /// Converts a Well-known Text representation to a <see cref="Geometry" />. /// </summary> /// <param name="reader"> /// A Reader which will return a Geometry Tagged Text /// string (see the OpenGIS Simple Features Specification) /// </param> /// <returns> /// Returns a <see cref="Geometry" /> read from StreamReader. /// An exception will be thrown if there is a parsing problem. /// </returns> public static Geometry GeometryFromWkt(TextReader reader) { var tokenizer = new WktStreamTokenizer(reader); return(ArcGISRuntimeWKT.GeometryFromWkt.ReadGeometryTaggedText(tokenizer)); }